0%

由于最近的工作有涉及到一些NLP的研究,而Bert的效果看起来不错,所以在原有方案上,基于相同的数据集(内部的任务数据集,所以暂时不会公开),做了一下效果对比.

只做一些简单的记录,以备自己将来回溯.

背景是基于中文句子分类.任务数据集在100万左右.

2080 on Pytorch.

原有方案

word2vec(200维度) + LSTM + Attention
网络结构比较简单,常规操作
训练 5 epoch大概需要10分钟左右.
准确率在77%左右.

Bert效果

中文预训练模型
训练 1 epoch大概需要200分钟.
准确率在76%左右.

Bert的一些备注

Bert有三个嵌入层,向量(Token)、上下部分(Segment)、位置(Position), 具体的一些解释可以参考
维度为768,所以比原来的高不少,这慢的一个原因(还有是因为网络结构比较复杂)
基于预训练模型在现有任务上训练一个epoch的效果最好,好像并不是训练的epoch越多越好,还不知道是为什么

其它

具体可以参考pytorch-pretrained-BERT,里面不止有Bert的预训练模型,还有一些其它模型的Pytorch实现,想要快速上手可以参考,特别是examples目录下的代码++

Bert是好,但并不一定在你的场景下也好,正式投产前还是需要做一些研究的.毕竟NLP这类的机器学习任务的数据集变化对模型的影响是很大的.

在Keras 中自定义可训练层

Bert预训练模型有12层或者24层,一般在起上层的Finetune任务会对所有层参数进行微调,也还有可能会在后面再接一些Layer.
但是,如果对所有层都进行微调的话,需要调整的参数量可能过大,12(约1.1亿), 24(2.2亿),耗时会比较久,如果只对后面几层或者特定层进行微调,可以是微调参数大大减少,训练实现也会加快.
主要可有参考:
Fine-tuning BERT with Keras and tf.Module
Finetuning BERT with Keras and tf.Module.ipynb
bert_experimental
TensorFlow Documentions
Keras Documentions

没卡是没法做深度学习的,所以决定斥资装一台服务器.

关于本文

本想边装边写指南,但是由于自己也是第一次装PC,还不定会成功呢,再者也不想写成流水账.所以在成功使用了一段时间之后以回忆录的方式记一下.
因为不是按装机步骤记录的指南,所以可能对装机也没什么参考价值.仅饭后小文而已.

前言

本来由于已经有一台MBP了,所以还考虑过的方案是给它配外接GPU,链接网站(egpu.io)是专门给MBP配eGPU的大神们分享经验的地方,如果有这个需求或许可以参考.
后来之所以放弃是因为:

  • MBP的CPU也不是很强(17款)
  • 内存也只有16G
  • 需要完全对接机器硬件、系统、GPU、电源等一些问题(会略复杂)
  • MBP是需要便携移动的,eGPU有点烦了
  • 干脆弄一台服务器,MBP来做数据探索、特征处理,服务器来跑代码,拓展性足够,两不耽搁(只是钱包略痛)

成本

成本来说的话,打算用于长期学习的话肯定自购硬件比较划算,毕竟随着时间的流逝,边际成本越来越低.
如果只是用个一时半会的肯定直接租用云平台了,在超出本地服务器要求时的短期需求也可以直接放在云平台上运行.

结果

过程虽有坎坷,结果还是OK的,但还有几个坑要提一下.
由于选了华硕x299主板,只能装win10(其实我想装Ubuntu啊++),系统原因又会导致一系列问题,比如NV、深度学习框架等等兼容性.在初学者的路上,任何一个小问题都可能使计划夭折在半路上,所以要慎重.主板的选择基本决定了系统,系统基本决定了平台和框架.所以要慎重.(选的时候注意主板和CPU/GPU的兼容基本就没啥问题了)
由于装的win10系统(在深度学习界并不是公认主流),导致TF-GPU安装一直报错失败,虽然参考官方文档进行了多次check,但依然没有解决,这就导致了keras基本处于不可用的状态.所幸Pytorch是可用的,不然我真是要洒泪了++,也就是现实将我逼上了Pytorch这座梁山.
装win系统还需要克制自己想装游戏的冲动,目前我还能克制.

过程

资料准备

资料来源主要参考了知乎上关于深度学习的装机指南帖子(https://www.zhihu.com/question/33996159?sort=created).

列配置

(此配置不具有参考性,请参考阅读时间当前的最新硬件及其兼容性[既然要装,这些也是逃不掉要学的,或早或晚,或交学费或没有])

  • 主板: WS X299
  • CPU: Inter i7 7820x
  • GPU: RTX 2080
  • 内存: 金士顿 16G*2
  • SSD: SAMSUNG
  • 水冷: 海盗船
  • 硬盘: WD 4T
  • 电源: CORSAIR
  • 显示器: PHILIPS 27
  • 机箱: AIR540
  • 鼠键: 罗技

Markdown

插线

设备买好之后,按照操作手册把线插好就行了.
当然,最复杂就是如何接主板上的接口,要多看两遍主板手册.
Markdown
(走线不是关键,走线再漂亮,点不亮也是白搭)

装系统

本以为,虽没装过操作系统,应该也能搞定.
殊不知,没搞定.
然后找了个专业装系统的,花了120,++.(没有启动盘).
Markdown
真是惭愧~

装软件

软件就比较简单了(但也不尽然,比如TF-GPU就没装好😢,道行还是不够啊).

写代码跑起来

测测GPU的安装成功与否.运行CUDA sample下的deviceQuery代码.
Markdown

后记

平台搭好,只是开始.
Markdown
后面的路还长.

人工智能的发展时间在计算机时代的历史中应该也不算短了.

至今(2019-02)所谓的强人工智能仍是一个遥不可及的问题.

要接受人的控制就必须要能够预测整个“智能”若干步骤后的状态,即没有不确定性,一切尽在掌控.那么这种掌控有可能产生智能吗?今天的人工智能行业的探索或许将给我们答案.

如果受基因进化思想的影响(交叉变异,环境选择),那么智能的发展过程中可能是充满不确定性的,这就从根本上与我们要求的控制形成了冲突和矛盾.

如果我们真的需要拥抱不确定性的话,初初想来确实也蛮可怕的.

我个人其实倾向于加入不确定性方可产生新的智能的方案.那么可能存在的问题应该怎么思考呢?
个人感觉可以参考人这个系统的方案,人中有好人和坏人.机器智能中有好的机器智能和坏的机器智能,是否可以将为人设计的机制以某种方式参照到机器智能中去呢?这样对于现存的人这个系统来说是不是就可以接受了?

目标是,只要加入了整个机器智能的系统后,带来的增益是大于成本的,总体上来说这个机制应该就可以存在下去.

背景

我们知道,线性代数的矩阵中,其实是没有矩阵除法这个概念的.

所以这里讲的相除其实是两个维度完全一样的矩阵对应点一一相除的意思.

类似于python 中np.array/np.array

1
2
3
4
import numpy as np
a = np.array([[1,2], [3,4]])
b = np.array([[2,3], [1,4]])
print("mat a is: \n {0} \n mat b is:\n {1} \n mat a/b is: \n {2}".format(a, b, a/b))
mat a is: 
 [[1 2]
 [3 4]] 
 mat b is:
 [[2 3]
 [1 4]] 
 mat a/b is: 
 [[0.5        0.66666667]
 [3.         1.        ]]

但是查阅Spark的官方文档

矩阵的乘法运算是通过 rowmatrix mutiply densematrix 来实现的,加法和减法都没有问题.

但是对应点一一相除则没有相关的方法来达到目的,所以需要自己做一些变通,其实也非常简单.

但是,由于Spark是在RDD的进行并行计算的,所以不能将数据拿出来到比如np.array来实现相关的算法,因为这需要将所有数据collect到某个节点的内存中进行,显然不OK.

注意到DenseVector在Spark中是有除法的,所以结果也很简单,将两个矩阵构造在两个Densevector 矩阵的RDD中,然后通过RDD1.zip(RDD2)同时操作两个RDD矩阵实现矩阵的除法.

构造矩阵

1
2
from pyspark import SparkContext
from pyspark.mllib.linalg.distributed import RowMatrix
1
sc = SparkContext('local', 'local_test_recommend')
1
2
3
4
5
6
rowsa = sc.parallelize([[1, 2], [3, 4]])
rowsb = sc.parallelize([[2, 3], [1, 4]])
sma = RowMatrix(rowsa)
smb = RowMatrix(rowsb)
print(sma.rows.collect())
print(smb.rows.collect())
[DenseVector([1.0, 2.0]), DenseVector([3.0, 4.0])]
[DenseVector([2.0, 3.0]), DenseVector([1.0, 4.0])]

矩阵相除

1
sma.rows.zip(smb.rows).map(lambda x: x[0]/x[1]).collect()
[DenseVector([0.5, 0.6667]), DenseVector([3.0, 1.0])]