Category Archives: ML&DL

使用Keras卷积神经网络

这篇文章记录如何用 Keras 实现 卷积神经网络 CNN,并训练模型用于图片分类;以及 CNN 中一些超参的调整和自己的理解。

数据集

http://www.ivl.disco.unimib.it/activities/large-age-gap-face-verification/

这个图片数据集是一些名人的少年时和成年后的对比照片,格式为 100*100,RGB。

将图片分成成年和少年两个类别,实现的分类器是个二分器,训练出来的模型能够对输入的照片进行分类,给出一个 old 或者 young 的 label。

整理数据集为如下目录结构:

train  
├── old
│   ├── 1200 张图片
├── young
│   ├── 1200 张图片

validation  
├── old
│   ├── 600 张图片
├── young
│   ├── 600 张图片

test  
├── old
│   ├── 110 张图片
├── young
│   ├── 110 张图片

train 为训练组,validation 为验证组,训练时使用交叉验证,train 和 validation 的数据都会使用。

test 为验证模型的测试组。

图片展示

以下是 train/old 组展示的部分图片:

%matplotlib inline

import os  
import matplotlib.pyplot as plt  
import matplotlib.image as mpimg

some_old_pics = os.listdir('train/old')  
show_rows = show_columns = 5  
for k in range(show_rows * show_rows):  
    image = mpimg.imread('train/old/%s' % some_old_pics[k])
    plt.subplot(show_rows, show_rows, k+1)
    plt.imshow(image)
    plt.axis('off')

“平均脸”

其实就是求每组图片的平均值,代码参考这里

import os, numpy, PIL  
from PIL import Image  
import matplotlib.pyplot as plt  
def plot_average_pic(group):  
    dirs = ["%s/%s" % (group, i) for i in ['old', 'young']]
    for k in range(len(dirs)):
        dir = dirs[k]
        imlist = ['%s/%s' % (dir, c) for c in os.listdir(dir)]
        w, h = Image.open(imlist[0]).size
        N = len(imlist)
        arr = numpy.zeros((h, w, 3), numpy.float)
        for im in imlist:
            imarr = numpy.array(Image.open(im), dtype=numpy.float)
            arr = arr + imarr / N
        arr = numpy.array(numpy.round(arr), dtype=numpy.uint8)
        image = Image.fromarray(arr, mode="RGB")
        plt.subplot(2, 3, k+1)
        plt.imshow(image)
        plt.title(dir)
        plt.axis('off')

结果如下:

好神奇 …

从“平均脸”这个结果来看,两组 label 确实有比较明显的区分。

创建 CNN 模型

导入的模块:

from keras.preprocessing.image import ImageDataGenerator  
from keras.models import Sequential  
from keras.layers import Conv2D, MaxPooling2D  
from keras.layers import Activation, Dropout, Flatten, Dense  

先定义好一些参数,所有图片的输入尺寸 (100*100,RGB 三通道),train / validation 样本数,训练轮次 epochs,以及小批量梯度下降训练样本值 batch_size:

img_width, img_height = 100, 100

train_data_dir = './train'  
validation_data_dir = './validation'  
nb_train_samples = 1200  
nb_validation_samples = 600  
epochs = 100  
batch_size = 16

input_shape = (img_width, img_height, 3)  

创建 CNN

model = Sequential()  
model.add(Conv2D(32, (3, 3), padding='same', input_shape=input_shape))  
model.add(Activation('relu'))  
model.add(MaxPooling2D(pool_size=(2,2)))

model.add(Conv2D(32, (3, 3), padding='same'))  
model.add(Activation('relu'))  
model.add(MaxPooling2D(pool_size=(2,2)))

model.add(Conv2D(64, (3, 3), padding='same'))  
model.add(Activation('relu'))  
model.add(MaxPooling2D(pool_size=(2,2)))

model.add(Flatten())  
model.add(Dense(64))  
model.add(Activation('relu'))  
model.add(Dropout(0.5))

model.add(Dense(1))  
model.add(Activation('sigmoid'))

model.compile(loss='binary_crossentropy',  
              optimizer='rmsprop',
              metrics=['accuracy'])

定义 train 和 validation 的 ImageDataGenerator,图像增强,用缩放、镜像、旋转等方式增加图片,以便扩大数据量:

train_datagen = ImageDataGenerator(  
    rescale=1. / 255,
    shear_range=0.2,
    zoom_range=0.2,
    horizontal_flip=True)
validation_datagen = ImageDataGenerator(  
    rescale=1. / 255)
train_generator = train_datagen.flow_from_directory(  
    train_data_dir,
    target_size=(img_width, img_height),
    batch_size=batch_size,
    class_mode='binary')
validation_generator = validation_datagen.flow_from_directory(  
    validation_data_dir,
    target_size=(img_width, img_height),
    batch_size=batch_size,
    class_mode='binary')

开始训练:

from keras.callbacks import ModelCheckpoint, Callback, TensorBoard  
filepath="1.weights-improvement-{epoch:02d}-{val_acc:.2f}.h5"  
checkpoint = ModelCheckpoint(filepath, monitor='val_acc', verbose=1, save_best_only=True, mode='max')  
tensorboard = TensorBoard(log_dir='logs', histogram_freq=0)  
callbacks_list = [checkpoint, tensorboard]

model.fit_generator(  
    train_generator,
    steps_per_epoch=nb_train_samples // batch_size,
    epochs=epochs,
    validation_data=validation_generator,
    validation_steps=nb_validation_samples // batch_size,
    callbacks=callbacks_list)

可以看到前几次训练之后验证组的准确率 ( val_acc ) 就可以达到 82% 左右了。

( 一个 epoch 用 i7 CPU 需要 180s,而 GTX1080 GPU 只需要 3s )

100 轮训练后成绩最好的结果:

loss: 0.2957 - acc: 0.8875 - val_loss: 0.2994 - val_acc: 0.9139  

val_acc 比 acc 还要高 …

Tenserboard 上看到的训练过程:

验证模型:

导入效果最好的模型

from keras.models import load_model  
best_model = load_model('a.weights-improvement-64-0.91.h5')  

还是用 ImageDataGenerator:

datagen = ImageDataGenerator()  
test_generator = datagen.flow_from_directory(  
        './test',
        target_size=(img_width, img_height),
        batch_size=batch_size,
        class_mode='binary')

验证:

scores = best_model.evaluate_generator(  
        test_generator,
        val_samples=220)
print scores  

结果:

[2.7107817684386277, 0.82976878729858838]

准确率达到了 82.98%,效果还不错,但是距离训练时的 91.39% 还有一定的差距,比较明显的过拟合。

dropout

将模型中倒数第三层的 Dropout 参数,降低为 0.2,增加模型的泛化能力:

model.add(Dropout(0.2))  

训练及测试结果:

[train] loss: 0.2599 - acc: 0.9008 - val_loss: 0.2315 - val_acc: 0.9105
[test]  loss: 2.1801 - acc: 0.8636 

准确率提升至 86.36% 。

optimizer

将 optimizer 从 rmsprop 更改为当前比较流行的 adam:

model.compile(loss='binary_crossentropy',  
              optimizer='adam',
              metrics=['accuracy'])

结果:

[train] loss: 0.1916 - acc: 0.9250 - val_loss: 0.3205 - val_acc: 0.9037
[test]  loss: 1.4704 - acc: 0.8962

准确率进一步提升为 89.62% 。

从这次模型来看,测试结果与训练结果相当接近。

kernel size

将卷积层的卷积核大小从 (3,3) 改为 (5,5)

Conv2D(32, (5, 5), padding='same', input_shape=input_shape)  

可以理解为增加了神经网络的权重参数数量,因为卷积层的权重参数数量,以第一层卷积层为例:

3 * (3 * 3) * 32 + 32 = 896  

增大为:

3 * (5 * 5) * 32 + 32 = 2432  

( 乘式前面的 3 为卷积层的深度,第一层是输入层的深度;后面的 32 为过滤器的个数,加上的 32 为 bias 个数,每个过滤器 1 个 bias )

结果:

[train] loss: 0.1104 - acc: 0.9533 - val_loss: 0.3632 - val_acc: 0.9003
[test]  loss: 1.7149 - acc: 0.8902

可以看到训练时的训练组准确率达到了 95.33% 的较高水平,反映了权重参数数量增多的正面影响。

然而测试结果来看,与未改变卷积核大小时反而有些微下降,或许还应该降低 Dropout 的比例。

在此基础上将 Dropout 比例由 0.2 再次下降为 0.1,结果如下:

[train] loss: 0.1321 - acc: 0.9500 - val_loss: 0.3917 - val_acc: 0.8970
[test]  loss: 1.4034 - acc: 0.9124

测试的准确率超过了 91% !

padding

将卷积层中的 padding 参数改为默认的 valid,即:

Conv2D(32, (5, 5))  

保持 0.2 的 Dropout 比例

结果:

[train] loss: 0.1768 - acc: 0.9208 - val_loss: 0.3337 - val_acc: 0.8986
[test]  loss: 1.7612 - acc: 0.8902

从结果来看并没多大的区别。

activation

测试更换激活函数。比如使用 PReLU,Keras 里使用 PReLU 需要使用 advanced_activations 类,模型修改如下:

from keras.layers.advanced_activations import PReLU

model = Sequential()  
model.add(Conv2D(32, (5, 5), input_shape=input_shape, activation='linear'))  
model.add(PReLU())  
model.add(MaxPooling2D(pool_size=(2,2)))

model.add(Conv2D(32, (5, 5), activation='linear'))  
model.add(PReLU())  
model.add(MaxPooling2D(pool_size=(2,2)))

model.add(Conv2D(64, (5, 5), activation='linear'))  
model.add(PReLU())  
model.add(MaxPooling2D(pool_size=(2,2)))

model.add(Flatten())  
model.add(Dense(64))  
model.add(Activation('relu'))  
model.add(Dropout(0.1))

model.add(Dense(1))  
model.add(Activation('sigmoid'))

model.compile(loss='binary_crossentropy',  
              optimizer='adam',
              metrics=['accuracy'])

需要先声明一个 linear 激活函数的卷积层,然后再在后面增加一个 PReLU 层。

因为 PReLU 实际上会增加权重参数数量,因此使用了 0.1 的 Droupout。

结果:

[train] loss: 0.2656 - acc: 0.8850 - val_loss: 0.2623 - val_acc: 0.9054
[test]  loss: 1.9551 - acc: 0.8737

试下 LeakyReLU(alpha=0.001)

[train] loss: 0.2002 - acc: 0.9267 - val_loss: 0.2987 - val_acc: 0.8885

然而在加载最佳结果 load_model 时有报错,没有执行最佳模型的测试。在最后一组训练得出的 val_acc: 0.8497 结果的模型上测试结果如下:

[test]  loss: 2.1069 - acc: 0.8688

batch size

训练时的 batch size 对训练模型也有一定的影响,具体可参考知乎上的讨论

实际测试如下:( 在之前 91% 测试准确率模型基础上修改 batch_size )

单从这个测试结果上看,还是 batch size 为 16 的最佳。

对比 batch size = 16 的训练过程,batch size = 8 的 acc 开始时上升较快,val_acc 震荡更为明显:

deeper

更深的网络。

再增加一层卷积层,模型修改如下:

model = Sequential()  
model.add(Conv2D(32, (5, 5), padding='same', input_shape=input_shape))  
model.add(Activation('relu'))  
model.add(MaxPooling2D(pool_size=(2,2)))

model.add(Conv2D(32, (5, 5), padding='same'))  
model.add(Activation('relu'))  
model.add(MaxPooling2D(pool_size=(2,2)))

model.add(Conv2D(64, (5, 5), padding='same'))  
model.add(Activation('relu'))  
model.add(MaxPooling2D(pool_size=(2,2)))

model.add(Conv2D(128, (5, 5), padding='same'))  
model.add(Activation('relu'))  
model.add(MaxPooling2D(pool_size=(2,2)))

model.add(Flatten())  
model.add(Dense(128))  
model.add(Activation('relu'))  
model.add(Dropout(0.1))

model.add(Dense(1))  
model.add(Activation('sigmoid'))

model.compile(loss='binary_crossentropy',  
              optimizer='adam',
              metrics=['accuracy'])

结果:

[train] loss: 0.2415 - acc: 0.9075 - val_loss: 0.3782 - val_acc: 0.8581
[test]  loss: 2.5879 - acc: 0.8361

可以看到过拟合严重了,或许对于数据量较少的训练集,使用更深的网络并不是一个较好的选择,比较容易出现过拟合。

最后

使用了测试结果为 91% 的模型,随便在谷歌上找了些图片进行测试,效果还不赖,如下图:

老年组 90% 准确率

温老四你怎么了 …

少年组 95% 准确率

詹老汉亮了。

参考

https://blog.keras.io/building-powerful-image-classification-models-using-very-little-data.html

from:https://zhengheng.me/2017/08/30/keras-cnn/

NLP入门之语音模型原理

作者:云时之间

这一篇文章其实是参考了很多篇文章之后写出的一篇对于语言模型的一篇科普文,目的是希望大家可以对于语言模型有着更好地理解,从而在接下来的NLP学习中可以更顺利的学习.

1:传统的语音识别方法:

这里我们讲解一下是如何将声音变成文字,如果有兴趣的同学,我们可以深入的研究.

首先我们知道声音其实是一种波,常见的MP3等都是压缩的格式,必须要转化成非压缩的纯波形的文件来处理,下面以WAV的波形文件来示例:

大数据
在进行语音识别之前,有的需要把首尾段的静音进行切除,进行强制对齐,以此来降低对于后续步骤的干扰,整个静音的切除技术一般称为VAD,需要用到对于信号处理的一些技术.

如果要对于声音进行分析,就需要对于声音进行分帧,也就是把声音切成一小块一小块,每一小块称为一帧,分帧并不是简单地切开,而是使用的移动窗函数来实现的,并且帧和帧之间一般是有交叠的

大数据
就像上图这样

分帧之后,语音就变成了很多个小段,但是波形在时域上是没有什么描述能力的,因此就必须要将波形进行变换,常见的一种变换方法就是提取MFCC特征,然后根据人耳的生理特性,把每一帧波变成一个多维度向量,这个向量里是包含了这块语音的内容信息,这个过程叫做声学特征的提取,但是实际方法有很多,基本类似.

至此,声音就成了一个12行(假设声学特征是12维)、N列的一个矩阵,称之为观察序列,这里N为总帧数。观察序列如下图所示,图中,每一帧都用一个12维的向量表示,色块的颜色深浅表示向量值的大小。

大数据
接下来就要介绍怎样把这个矩阵变成文本了。首先要介绍两个概念:

1:音素:

单词的发音由音素构成。对英语,一种常用的音素集是卡内基梅隆大学的一套由39个音素构成的音素集,参见The CMU Pronouncing Dictionary‎。汉语一般直接用全部声母和韵母作为音素集,另外汉语识别还分有调无调,不详述。

1. 状态:这里理解成比音素更细致的语音单位就行啦。通常把一个音素划分成3个状态。

语音识别是怎么工作的呢?实际上一点都不神秘,无非是:

把帧识别成状态(难点)。

把状态组合成音素。

把音素组合成单词。

如下图所示:

大数据
图中,每个小竖条代表一帧,若干帧语音对应一个状态,每三个状态组合成一个音素,若干个音素组合成一个单词。也就是说,只要知道每帧语音对应哪个状态了,语音识别的结果也就出来了。

那每帧音素对应哪个状态呢?有个容易想到的办法,看某帧对应哪个状态的概率最大,那这帧就属于哪个状态。比如下面的示意图,这帧在状态S3上的条件概率最大,因此就猜这帧属于状态S3。

大数据
那这些用到的概率从哪里读取呢?有个叫“声学模型”的东西,里面存了一大堆参数,通过这些参数,就可以知道帧和状态对应的概率。获取这一大堆参数的方法叫做“训练”,需要使用巨大数量的语音数据,训练的方法比较繁琐,这里不讲。

但这样做有一个问题:每一帧都会得到一个状态号,最后整个语音就会得到一堆乱七八糟的状态号。假设语音有1000帧,每帧对应1个状态,每3个状态组合成一个音素,那么大概会组合成300个音素,但这段语音其实根本没有这么多音素。如果真这么做,得到的状态号可能根本无法组合成音素。实际上,相邻帧的状态应该大多数都是相同的才合理,因为每帧很短。

解决这个问题的常用方法就是使用隐马尔可夫模型(Hidden Markov Model,HMM)。这东西听起来好像很高深的样子,实际上用起来很简单: 第一步,构建一个状态网络。 第二步,从状态网络中寻找与声音最匹配的路径。

这样就把结果限制在预先设定的网络中,避免了刚才说到的问题,当然也带来一个局限,比如你设定的网络里只包含了“今天晴天”和“今天下雨”两个句子的状态路径,那么不管说些什么,识别出的结果必然是这两个句子中的一句。

那如果想识别任意文本呢?把这个网络搭得足够大,包含任意文本的路径就可以了。但这个网络越大,想要达到比较好的识别准确率就越难。所以要根据实际任务的需求,合理选择网络大小和结构。

搭建状态网络,是由单词级网络展开成音素网络,再展开成状态网络。语音识别过程其实就是在状态网络中搜索一条最佳路径,语音对应这条路径的概率最大,这称之为“解码”。路径搜索的算法是一种动态规划剪枝的算法,称之为Viterbi算法,用于寻找全局最优路径。

大数据
这里所说的累积概率,由三部分构成,分别是:

  1. 观察概率:每帧和每个状态对应的概率
  2. 转移概率:每个状态转移到自身或转移到下个状态的概率
  3. 语言概率:根据语言统计规律得到的概率

其中,前两种概率从声学模型中获取,最后一种概率从语言模型中获取。语言模型是使用大量的文本训练出来的,可以利用某门语言本身的统计规律来帮助提升识别正确率。语言模型很重要,如果不使用语言模型,当状态网络较大时,识别出的结果基本是一团乱麻。

这样基本上语音识别过程就完成了。

2:端到端的模型

现阶段深度学习在模式识别领域取得了飞速的发展,特别是在语音和图像的领域,因为深度学习的特性,在语音识别领域中,基于深度学习的声学模型现如今已经取代了传统的混合高斯模型GMM对于状态的输出进行建模,因此在普通的深度神经网络的基础之上,基于长短记忆网络的递归神经网络对语音序列的强大的建模能力进一步提高了语音识别的性能,但是这些方法依旧包含着最基础的隐马尔可夫HMM的基本结构,因此依旧会出现隐马尔科夫模型的训练和解码的复杂度问题.

基于深度学习的声学模型训练过程必须是由传统的混合高斯模型开始的,然后对训练数据集合进行强制的对齐,然后进行切分得到不同的声学特征,其实传统的方式并不利于对于整句话的全局优化,并且这个方法也需要额外的语音学和语言学的知识,比如发音词典,决策树单元绑定建模等等,搭建系统的门槛较高等问题.

一些科学家针对传统的声学建模的缺点,提出了链接时序分类技术,这个技术是将语音识别转换为序列的转换问题,这样一来就可以抛弃了传统的基于HMM的语音识别系统的一系列假设,简化了系统的搭建流程,从而可以进一步提出了端到端的语音识别系统,减少了语音对于发音词典的要求.

端到端的系统是由LSTM的声学建模方法和CTC的目标函数组成的,在CTC的准则下,LSTM可以在训练过程中自动的学习声学的特征和标注序列的对应关系,也就不需要再进行强制的对数据集合进行对齐的过程了.并且可以根据各种语种的特点,端到端识别直接在字或者单词上进行建模,但是因为端到端的识别可能是意味着发展的趋势,但是因为完全崛弃了语音学的知识,现如今在识别性能上仍然和传统的基于深度学习的建模方法有着一定的差距,不过我最近在看的一篇论文中,基于端到端的藏语识别已经达到甚至超过了现有的通用算法.

就拿藏语举例,藏语是一种我国的少数民族语言,但是因为藏族人口较少,相比起对于英文,汉语这样的大语种来说,存在着语音数据收集困难的问题,在上一篇文章中我们可以知道,自然语言处理的最重要的需求就是语料,如果有很好的语料库自然会事半功倍,这样就导致了藏语的语音识别研究工作起步较晚,并且因为藏语的语言学知识的匮乏进一步阻碍了藏语语音识别的研究的进展,在我国,藏语是属于一种单音节字的语言,在端到端的语音过程中,藏语是建模起来非常简单的一种语言,但是作为一种少数民族语言,语料不足会在训练过程中出现严重的稀疏性问题,并且很多人在研究现有的藏语词典中发现,如果完全崛弃现有的藏语发音词典,完全不利用这样的先验知识,这样其实也是不利于技术的发现的,因此现阶段下,采用CTC和语言知识结合的方式来建模,可以解决在资源受限的情况下声学的建模问题,使得基于端到端的声学模型方法的识别率超过当下基于隐马尔科夫的双向长短时记忆模型.

在基于CD-DNN-HMM架构的语音识别声学模型中,训练DNN通常需要帧对齐标签。在GMM中,这个对齐操作是通过EM算法不断迭代完成的,而训练DNN时需要用GMM进行对齐则显得非常别扭。因此一种不需要事先进行帧对齐的方法呼之欲出。此外对于HMM假设一直受到诟病,等到RNN出现之后,使用RNN来对时序关系进行描述来取代HMM成为当时的热潮。随着神经网络优化技术的发展和GPU计算能力的不断提升,最终使用RNN和CTC来进行建模实现了end-to-end语音识别的声学模型。CTC的全称是Connectionist Temporal Classification,中文翻译大概是连接时序分类。它要达到的目标就是直接将语音和相应的文字对应起来,实现时序问题的分类。

这里仍然可以描述为EM的思想:

E-step:使用BPTT算法优化神经网络参数;

M-step:使用神经网络的输出,重新寻找最有的对齐关系。

CTC可以看成是一个分类方法,甚至可以看作是目标函数。在构建end-to-end声学模型的过程中,CTC起到了很好的自动对齐的效果。同传统的基于CD-DNN-HMM的方法相比,对齐效果引用文章[Alex Graves,2006]中的图是这样的效果:

大数据
这幅图可以理解:基于帧对齐的方法强制要求切分好的帧对齐到对应的标签上去,而CTC则可以时帧的输出为空,只有少数帧对齐到对应的输出标签上。这样带来的差别就是帧对齐的方法即使输出是正确的,但是在边界区域的切分也很难准确,从而给DNN的训练引入错误。c) End-to-end模型由于神经网络强大的建模能力,End-to-end的输出标签也不再需要像传统架构一样的进行细分。例如对于中文,输出不再需要进行细分为状态、音素或者声韵母,直接将汉字作为输出即可;对于英文,考虑到英文单词的数量庞大,可以使用字母作为输出标签。从这一点出发,我们可以认为神经网络将声学符号到字符串的映射关系也一并建模学习了出来,这部分是在传统的框架中时词典所应承担的任务。针对这个模块,传统框架中有一个专门的建模单元叫做G2P(grapheme-to-phoneme),来处理集外词(out of vocabulary,OOV)。在end-to-end的声学模型中,可以没有词典,没有OOV,也没有G2P。这些全都被建模在一个神经网络中。另外,在传统的框架结构中,语音需要分帧,加窗,提取特征,包括MFCC、PLP等等。在基于神经网络的声学模型中,通常使用更裸的Fbank特征。在End-to-en的识别中,使用更简单的特征比如FFT点,也是常见的做法。或许在不久的将来,语音的采样点也可以作为输入,这就是更加彻底的End-to-end声学模型。除此之外,End-to-end的声学模型中已经带有了语言模型的信息,它是通过RNN在输出序列上学习得到的。但这个语言模型仍然比较弱,如果外加一个更大数据量的语言模型,解码的效果会更好。因此,End-to-end现在指声学模型部分,等到不需要语言模型的时候,才是完全的end-to-end。3、 语言模型(Language Model, LM)语言模型的作用可以简单理解为消解多音字的问题,在声学模型给出发音序列之后,从候选的文字序列中找出概率最大的字符串序列。

4、 解码传统的语音识别解码都是建立在WFST的基础之上,它是将HMM、词典以及语言模型编译成一个网络。解码就是在这个WFST构造的动态网络空间中,找到最优的输出字符序列。搜索通常使用Viterbi算法,另外为了防止搜索空间爆炸,通常会采用剪枝算法,因此搜索得到的结果可能不是最优结果。在end-to-end的语音识别系统中,最简单的解码方法是beam search。尽管end-to-end的声学模型中已经包含了一个弱语言模型,但是利用额外的语言模型仍然能够提高识别性能,因此将传统的基于WFST的解码方式和Viterbi算法引入到end-to-end的语音识别系统中也是非常自然的。然而由于声学模型中弱语言模型的存在,解码可能不是最优的。文章[yuki Kanda, 2016]提出在解码的时候,需要将这个若语言模型减掉才能得到最优结果。

End.

转载请注明来自36大数据(36dsj.com):36大数据 » NLP入门之语音模型原理

谷歌大神Jeff Dean:大规模深度学习最新进展

在AlphaGo与李世石比赛期间,谷歌天才工程师Jeff Dean在Google Campus汉城校区做了一次关于智能计算机系统的大规模深度学习(Large-Scale Deep Learning for Intelligent Computer Systems)的演讲。本文是对他这次演讲的总结。完整演讲视频(如下):

如果你无法理解信息里包含的内容,那么就会很难将其组织起来。

自从AlphaGo与李世石的比赛——这是约翰·亨利对战蒸汽锤的现代版本——吸引了全世界,再次滋生了对「人工智能毁灭世界」的恐惧感,似乎此时一睹Jeff的演讲是绝佳时刻。如果你认为AlphaGo现在很好,就等待它的beta版本吧。

Jeff当然提到了谷歌的著名语录:组织这个世界的信息,使信息唾手可得并变得有用。

过去,我们可能会将「组织」和收集、清除、存储、索引、报告和搜索数据联系起来。所有这些都是谷歌早期精通的业务。而这些任务完成后,谷歌已经开始进行下一项挑战了。

现在,组织意味着理解。

此次演讲的一些重点:

真正的神经网络由几亿个参数组成。谷歌现在所拥有的技能在于如何建造并快速训练这些大型模型来处理大量数据集,并用它们去解决实际问题,之后快速将这些模型部署到不同平台上的大量产品中(手机、传感器、云等等)。

神经网络在90年代没有得到快速发展是由于缺乏足够的计算能力和大型的数据集。你能看到谷歌对算法的天然热爱是如何与他们的大量基础设施结合到一起的,也能看到不断扩大的数据集如何为谷歌的人工智能创造了完美的推动。

谷歌和其他公司的一个关键区别就在于,当他们在2011年启动谷歌大脑计划时,他们并没有将他们的研究独立成该公司一个单独的研究部门,成为象牙塔一般的存在。而是项目团队和其他团队紧密合作,比如安卓、Gmail 和photo等部门,以确实改进它们的特性,解决困难的问题。这对每一家公司来说都是非常珍贵的一刻。通过和你的人一起工作将研究进行实际应用。

这一想法十分强大:他们知道他们能够获取完整的子系统,有些可能是机器学习到的,用更加通用的端对端的机器学习块进行替换。通常当你有很多复杂的子系统时,总会有很多复杂的代码将这些系统拼接起来。如果能够用数据和非常简单的算法将这一切进行替换的话就再好不过了。

机器学习很快将会变得更好。引用Jeff的话说:机器学习领域的发展非常快。一篇论文发布出来,一周内全球众多研究团体会下载这篇论文,阅读、解析论文,验证论文的内容,然后把自己对论文的延展发布到arXiv.org上。这与计算机学的其他领域不同,他们首先需要提交文件,而后六个月会议讨论决定是否接收,再过三个月会议上才会有结果。这就耗费了一年时间。电子论文能把这个时间压缩到一周是非常惊人的。

技术能够非常神奇的结合起来。谷歌翻译团队写了一个APP,能够使用计算机视觉在取景器上识别文本。在翻译完文本后,可以把翻译后的内容自动添加到图片上。另外一个例子是写图片字幕。把图片识别和一序列一序列的神经网络结合起来。可以想象,这些模块化的内容在未来将何等紧密的结合起来。

有强大功能的模型要小到足以在智能手机上运行。科技想要想取代智力必须走到这一步。它不能依靠网络连接外部的「云大脑」。既然TensorFlow模型能够在手机上运行,那这一点是有可能实现的。

如果你还没有思考深度神经网络如何解决数据理解问题,那你就要开始思考了。这条起始线从现在开始,但它的实现是非常明了的,我们看到了很多难题在深度学习网络面前都迎刃而解。

Jeff 发表的讲话都非常的棒,这次毫不例外。内容非常直接有趣,有深度,还非常容易理解。如果你想了解深度学习或了解Googel打算做什么,这些内容就值得一看了。

理解意味着什么?

当一个人看到街道景象时,他能轻而易举地挑选出图片上的文本,了解到有的商店卖纪念品,有家店价格特别低等信息。但直到现在,计算机依然不能从图片中提取出这些信息。

170007kiymh23gx8zg28i7.jpg

如果计算机想要从图片中了解现实世界,它需要能够从中挑选出有趣的信息点,阅读文本并理解它。

在未来,小型移动设备将主宰着计算机交互。这些设备都需要不同类型的界面。需要真的能够理解并生成对话。

我们在搜索引擎中输入:[汽车零部件]。旧的谷歌版本会因为关键词匹配给你第一条结果,但更好的结果其实是第二个结果。真正的理解是这个问题深层次的意义是什么,并非字眼的表面意义。这才是构建好的搜索与语言理解产品所需要的。

170008plfww7fk2woqw75o.jpg

谷歌深度神经网络小历史

谷歌大脑计划于2011年启动,聚焦于真正推动神经网络科学能达到的最先进的技术。

神经网络已经存在很多年了,出现于19世纪60年代至70年代之间,在80年代晚期和90年代早期红极一时,然后逐渐暗淡。主要因为两个问题:1)缺乏必备的计算能力去训练大量的模型,这意味着神经网络不能应用于包含大量有趣的数据集的大型问题。2)缺乏大量的有趣的数据集。

谷歌开始只有几个产品团队工作。随着这些团队发布一些很好的、能解决以前不能解决的问题的产品。名声渐起,很快,更多的团队加入其中帮助解决问题。

谷歌需要利用深度学习技术的产品/领域:安卓,Apps,药物发现,谷歌邮箱,图像理解,地图,自然语言,图片,机器人,语音翻译,等等。

深度学习能应用于如此完全不同的项目的原因是他们涉及相同的基石,这些基石可用于不同的领域:语音、文本、搜索查询、图像、视频、标签、实体(一种特定的软件模块)、文字、音频特性。你可以输入一种类型的信息,决定你想要输出信息类型,收集训练数据集指示出你想要计算的功能。然后,你可以放手不管了。

这些模型十分奏效,因为你输入的是非常原始的数据。你不必给出数据大量的有趣特点,模型的力量足以让它自动地通过观察许多许多例子决定数据集的有趣之处。

你可以学习常见的表征,这种学习很可能是跨领域的。例如,一辆『汽车』可以指图像中与真实相同的汽车。

他们已经学到他们可以聚集一大堆的子系统,其中一些可能是由机器学习的,然后用更通用的端对端的机器学习块代替它。通常当你有很多复杂的子系统时,往往有大量复杂的代码将这些子系统缝结在一起。如果你能用数据和简单的算法代替所有复杂代码,那就太好了。

什么是单个深度神经网络?

神经网络从数据中学习真正复杂的函数。从一端输入内容转换成另一端的输出内容。

这一函数不像计算x2,而是真正复杂的函数。当你输入原始像素,比如一只猫是,输出结果就会是事物的类别。

170050i80a2do1o3zy80yg.png

深度学习中的「深度」是指神经网络的层的数量。

对于深度,一个好的属性是系统是由简单的可训练的数学函数的集合构成的。

深度神经网络与大量机器学习方式是兼容的。

例如,你输入猫的图片,输出的是一张人为标注为猫的图像,这叫作监督式学习。你可以给系统列举大量的监督式样例,并且将学习结合一个函数,这个函数与在监督式例子所描述的是相似的。

你也可以进行非监督式训练,你只得到图像而不知道图像里面的什么。然后系统可以依靠在众多图片中出现的模式学会挑选。所以,即使不知道图像叫作什么,它也可以在所有这些有猫的图形辨别出共同的事物来。

这也和更多像强化学习这样的外来技术是兼容的。强化学习是非常重要的技术,它正在被AlphaGo使用。

什么是深度学习?

神经网络模型可以说是基于我们所认识的大脑运作的方式,它并不是对神经元真正工作的详细模拟,而是一个简单抽象的神经元版本。

170008hwjxwajxw66wawwm.jpg

一个神经元能够接收许多输入信息,真实的神经元会将不同的优势(strengths)与不同的输入相联系。人工智能网络试着学习为所有那些边缘,亦即与这些不同输入关联的优势进行加权。

真实的神经元吸收一些输入与优势的组合,并决定是否发出一个脉冲。人工神经元不仅仅会发出脉冲,还会发出一个实数值。这些神经元计算的函数是输入的加权求和乘以非线性函数的权重。

现今通常所用的非线性函数是ReLU(max(0,x))。在上世纪九十年代,大部分非线性函数都是更加平滑 (https://www.quora.com/What-is-special-about-rectifier-neural-units-used-in-NN-learning)的 sigmoid或tanh函数。当神经元不放电的时候会取真正的零值,而不是非常接近零的数值的优秀特性,从而帮助优化系统。

例如,如果神经元有着三个输入X1,X2,X3,分别有着0.21,0.3,0.7的权重,那么计算函数将为:y = max(0, -.0.21*x1 + 0.3*x2 + 0.7*x3)。

在识别图片里是一只猫还是一只狗的过程中,图像会经过多层级处理,基于它们的输入神经元可以决定是否发射脉冲。

170008mv90e91mit1zwtm1.jpg

最底层的神经元只处理一小部分像素,更高层的神经元则会处理下层神经元的输出并决定是否发射脉冲。

模型会如此向上直至最后一层处理完毕,举个例子,这是一只猫。在这种情况下它错了,这是一只狗(尽管我也认为那是一只猫,那是一只在篮子里的狗吗?)。

输出错误的信号会反馈回系统中,接着其余模型会做出调整以让它在下一次处理图片时更有可能给出正确的答案。

调整整个模型所有的边缘权重以增大获得正确结果的可能性,这就是神经网络的目标。人们在所有的样本都如此处理,这样在大部分的样本中都会得到正确的输出。

学习算法非常简单。循环计算步骤如下:

随机选择一个训练样本「(输入,标签)」。例如,一张猫的图片,以及预期输出「猫」。

用「输入」运行神经网络,并观察它的结果。

调整边缘权重,让输出更接近与标签」。

该如何调整边缘权重以让输出接近标签呢?

反向传播法:这里是一篇针对此的推荐文章:Calculus on Computational Graphs: Backpropagation (http://colah.github.io/posts/2015-08-Backprop/)。

当神经网顶层选择的是猫而不是狗的时候,通过微积分链式法则来调整权重参数使得网络可以做更准确的预测。

170008znz6akknu8k6v7as.jpg

你需要和权重的箭头保持同一方向,让它更有可能认为这是一只狗。不要跳一大步,因为这可是一个复杂坎坷的表面。小步前进会让结果在下一次更有可能变成狗。通过大量迭代以及对样本的观察,结果就越有可能变成狗。

通过链式法则你可以理解底层的参数变化会如何影响输出。这意味着神经网络网络的变化如同涟漪般波及至输入,调整整个模型,并增大它说出狗的可能性。

真的神经网络由数以亿计参数组成,因此你正在一个亿维空间内做调整,并试着理解那是怎样影响网络输出结果的。

神经网络的很多优秀特性

神经网络可以运用到多个不同领域,用来解决不同的问题:

文本:英语和其他语言包含数万亿的单词。现有很多对应的文字资料,包含句与句对应的一种源语言文字与其翻译版的另一种语言文字。

视觉数据:数十亿的图像和视频。

声音:每天会产生几万小时的音频数据;

用户行为:不同的应用程序都在产生数据,无论你在搜索引擎敲下的字符还是在邮箱里标记的垃圾邮件,这些用户行为里可以不断被学习,并用来给你「定制」智能系统。

知识图谱:数十亿打标签的RDF triple数据。

你给的数据越多,其反馈的结果越好,你也会让这个模型更大。

如果你投入更多的数据却不去扩大你的模型,会进入一个模型能力的饱和状态,此时,模型学习到的只是关于你的数据集最显而易见的事实。

通过增加模型的规模,模型不仅可以记住一些明显的特征,还会记住一些只是偶然在数据集中出现的细微特征。

打造更大的模型需要更多数据和更强大的计算能力。谷歌一直在做的就是如何规模化计算量并投入到这些问题的解决中,从而训练更大的模型。

深度学习给谷歌带来哪些影响?

语音识别

语音识别团队第一个和谷歌大脑团队合作部署神经网络。在谷歌大脑团队帮助下,部署上线了一个新的、基于神经网络的语音模型,不再使用之前的隐马尔科夫模型。

声学模型的问题是从150毫秒的语音里预测其中10毫秒的声音是什么。类似与「ba」还是「ka」。接着你有了这些预测的完整序列,然后将它们和语言模型对接起来,以理解用户在说什么。

这个模型将识别错误率降低了30%,意义非常重大。此后语音团队继续在构建更加复杂的模型,并结合更好的神经网络降低错误率。现在你在手机上说话,语音识别已经比三到五年前好太多了。

Image 挑战赛

大约六年前, ImageNet的数据库公开,大约有100万图像数据,这个巨大的图像数据库对于推进计算机视觉的发展意义重大。

图像被分为1000个不同种类,每个种类大约1000张照片;

大约有1000张不同的豹子照片、1000张不同的汽车、滑板车照片等等;

其中有个复杂的因素:并非所有的标签都是正确的;

比赛的目标是概括出照片的新的类型。对于一张新照片,你能判断出来上面是猎豹还是樱桃吗?

在神经网络运用到比赛之前,这项比赛的错误率为26℅。2014年,谷歌赢得比赛时的错误率为6.66%。2015年的时候,获胜团队的错误率降低到3.46%。

这是一个巨大而且有深度的模型。每个盒子都布满了完整层级的神经元,它们正在进行卷积运算,关于这方面的详细情况,可以查看这篇论文《Going Deeper with Convolutions》

170008vm9rb9h9j5jqabzi.jpg

一个名叫 Andrej Karpathy 的人也参与了比赛,他的错误率是5.1%,他后来还写了篇文章《What I learned from competing against a ConvNet on ImageNet.》

神经网络模型擅长什么?

神经网络模型非常擅长识别精细程度的差别。比如,计算机擅长辨别人类不善于分辨的犬种。人类可能看到一朵花就只知道那是一朵花,计算机可以分辨那是一朵「芙蓉」或是一朵「大丽花」。

神经网络模型擅长归纳。比如不同种类的饭菜,尽管看起来不一样,但都会被标记为「饭菜」。

当计算机出错时,错误的原因是合理的。比如一只蛞蝓看起来很像一条蛇。

谷歌照片搜索

检查照片的像素并理解图像中的内容,这是个很强大的能力。

Google Photos 团队在没有标记它们的情况下部署了这一能力。你可以在没有标记图片的情况下搜索到雕像、尤达、图画、水等图片。

街景影像

在街景影像中,你希望可以阅读到所有的文本。这是更为精细更为具体的视觉任务。

首先需要能够找到图像中的文本。模型基本上都是被训练用来预测像素热图的:哪些像素包含文本,哪些不包含。训练数据是绘制于文本像素周围的多边形。

因为训练数据包含不同的字符集,它可以找到多种不同语言的文本。它可以识别大字体和小字体,离镜头近的和离得很远的文字,以及不同颜色的文本。

这是一个训练相对简单的模型。这是一个试图预测每个像素是否包含文本的传统的网络。

谷歌搜索排名的RankBrain

RankBrain于2015年推出,是谷歌第三重要的搜索排名因素。了解更多:谷歌将其利润丰厚的网络搜索交给人工智能机器。

搜索排名是不同的,因为你想要能够理解该模型,你想理解为什么它会做出特定的决策。

这是搜索排名团队犹豫在搜索排名中使用神经网络的一个原因。当系统出错时,他们希望了解什么会这样。

调试工具已被制造出来,而且模型也能被充分地理解,以克服这种异议。

一般来说你不想手动调整参数。你尝试理解为什么模型会做出那样的预测并搞清楚是否与训练数据相关,是与问题不匹配吗?你可能在一个分布式数据上进行训练,然后将其应用于另一个。通过搜索查询的分布,模型每天都能获得一点改变。因为事件在改变,模型也一直在改变。你必须了解你的分布是否是稳定的,比如在语音识别中,人们的声音并不会发生太大改变。查询和文档内容经常在改变,所以你必须确保你的模型是新鲜的。更一般地,我们需要打造更好的用于理解这些神经网络内部状况的工具,搞清楚是什么得出了预测。

序列至序列(Sequence-to-Sequence)映射模型

世界上许多问题都可归入到一个序列映射到另一个序列的框架中。谷歌的Sutskever、Vinyals 和 Le 在这个主题上写了一篇开关性的论文:使用神经网络的序列到序列学习 (http://papers.nips.cc/paper/5346-sequence-to-sequence-learning-with-neural-networks.pdf)。

特别地,他们研究了语言翻译,将英语翻译成法语中的问题。翻译事实上只是将英语句子序列映射到法语句子序列。

神经网络非常擅长学习非常复杂的功能,所以这个模型学习了映射英语句子到法语句子的功能。

170009nfzopeod6jkhp6pr.jpg

一种语言的一个句子通过EOS(end of sentence)信号一次输入一个词。当模型看到EOS 开始产出其它语言对应的句子时,模型就得到了训练。训练数据是具有同样含义的不同语言中的配对句子。它只是试图该函数建模。

模型会在每一步发出你的词汇中所有词条输入的概率分布。在推理而不是训练时间,你需要做一点搜索。如果你必须最大化每个词的概率,你并不一定会得到最可能的句子。直到找到最大可能的句子,联合概率的搜索才完成。

该系统是现在公共翻译服务中最先进的。其它翻译系统是一堆手写的代码或这个翻译问题的子块的机器学习模型,而非完全的端到端学习系统。

人们对这一模型的兴趣在暴增,因为很多问题都可被映射到序列到序列的方法。

智能回复(Smart Reply)

Smart Reply是序列到序列在产品中的一个应用案例。在手机上,你希望快速回复邮件,而打字又让人痛苦。

和 Gmail 团队合作,他们开发了一个能预测一条信息可能的回复的系统。

第一步是训练一个小模型以预测一条信息是否是可以快速回复的信息。如果是,就会激活一个更大的计算上更昂贵的模型;该模型将该信息作为一个序列,并尝试预测回复的单词序列。

比如,对于一封询问感恩节邀请的电子邮件,可预测到的回复有三个:把我们算上;我们会去;抱歉我们去不了。

Inbox 应用中惊人数量的回复都是通过 Smart Reply 生成的。

图片说明

生成一张图片说明时,你会试着让机器尽可能写出类似人类基于图片会做出的说明。

采用已经开发出来的图片模型,以及已经研发出来的Sequence-to-Sequence模型,把它们插在一起。图片模型被用作输入。

它被训练用来生成说明。训练数据集拥有五种不同的人给出的五种不同说明的图片。10万到20万的图片需要写70万句的说明。

一张婴儿怀抱泰迪熊的图片,电脑这么写的:一个抱着填充玩具动物孩子的特写;一个婴儿在泰迪熊旁边睡着了。

还没有达到人类理解水平,但机器出错时,结果可能会有趣。

综合视觉+翻译

技术能够综合起来。翻译团队编写了使用了在取景器中识别文本的计算机视觉APP。翻译文本,然后给图片叠加翻译文本(让人印象非常深刻,约37;29)。

模型足够小,整个计算都在设备上运行。

迭代(turnaround)时间和对研究的影响

在一天内完成单个CPU花费6周才能完成的训练

谷歌真的关心能够快速迭代研究。它的想法是快速的训练模型。理解什么运行良好,什么运行欠佳,找出下一组要运行的实验。

一个模型应该在在几分钟几小时内就能可训练,而不是几天甚至几个礼拜。让每个做这类研究的人更加富有生产力。

如何快速训练模型?

模型的并行性

一个神经网络有许多内在的并行性。

所有不同的个体神经元几乎都是彼此独立的,当你计算它们时,特别是,加入你有Local Receptive Fields,这是一个神经元从其下方少量神经元那里接受输入的地方。

能够跨越不同GPU卡上的不同机器对工作进行划分,只有跨越边界的数据才需要交流。

170010ll6vm9qjd2q96doh.jpg

数据的并行性

当你对模型的参数集进行优化时,不应该在中央服务的一台机器上进行,这样你就有不同的模型副本,通过它们之间的合作来进行参数优化。

在训练中理解不同的随机数据片段。每一个副本都会获得模型中当前的参数集,通过对相当规模数据的理解来判断出梯度,找出需要对参数所作的调整,并且将调整值发回至中央参数集服务器。参数服务器会对参数进行调整。不断重复这个过程。

这会在多个副本之间完成。有时他们会使用500台机器来生成500个模型副本,以便迅速实现参数的优化和处理数据。

这个过程可以异步进行,每个数据分任务在各自独自的循环运算中,获取参数,计算梯度并将它们传回,不会受到其他彼此的控制和同步。结果是,按照50-100的副本规模进行练习,对许多模型来说是可行的。

Q&A

如果不是诸如谷歌这样的大公司,无法获取海量数据集,你会怎么做?从一个运行良好的模型开始,用公共数据集进行训练。公共数据集普遍可以获取。然后用更加适合你问题的数据进行训练。当你从一个类似并且公开可获取的数据组开始时,针对你的特殊问题,可能只需要1,000或者10,000标签实例。ImageNet就是这种处理可行的好例子。

身为一个工程师,你所犯过的最大错误是什么?没有在BigTable里放入分布式事务处理能力。如果你想要更新多条数据,你不得不运作你自己的事务处理流程。没有放入事务处理能力是因为会增加系统设计的复杂度。回想起来,很对团队想要有那种能力,他们各自独立(在上层)去添加这个能力,也获得了不同程度成功。我们应该在核心系统实现事务处理能力。它在内部应用场景也会很有用。Spanner系统增加了事务处理搞定了这个问题。

英文链接:Jeff Dean on Large-Scale Deep Learning at Google

机器学习驱动编程:新世界的新编程

如果今天要重新建立Google,这家公司的大部分系统将会是通过学习得来的,而非编写代码而来。Google的25,000名开发者中原本有大概10%精通机器学习,现在这一比例可能会达到100% — Jeff Dean

和天气一样,大家都会抱怨编程,但谁也没有为此做点什么。这种情况正在发生变化,就像突如其来的暴风雨一样,这些变化也来自一个出乎意料的方向:机器学习/深度学习。

我知道很多人对深度学习都听厌了。谁不是呢?但是编程技术很长时间来都处在一成不变的情况下,是时候做点什么改变这一情况了。

各种有关编程的“战斗”还在继续,但解决不了任何问题。函数还是对象,这种语言还是那种语言,这朵公有云还是那朵公有云或者这朵私有云亦或那朵“填补了空白”的云,REST还是Unrest,这种字节级编码还是另一种编码,这个框架还是那个框架,这种方法论还是那种方法论,裸机还是容器或者虚拟机亦或Unikernel,单层还是微服务或者NanoService,最终一致还是事务型,可变(Mutable)还是不可变(Immutable),DevOps还是NoOps或者SysOps,横向扩展还是纵向扩展,中心化还是去中心化,单线程还是大规模并行,同步还是异步。诸如此类永无止境。

年复一年,天天如此。我们只是创造了调用函数的不同方法,但最终的代码还需要我们人类来编写。更强大的方法应该是让机器编写我们需要的函数,这就是机器学习大展拳脚的领域了,可以为我们编写函数。这种年复一年天天如此的无聊活动还是交给机器学习吧。

机器学习驱动的编程

我最初是和Jeff Dean聊过之后开始接触用深度学习方式编程的。当时我针对聊天内容写了篇文章:《Jeff Dean针对Google大规模深度学习的看法》。强烈建议阅读本文了解深度学习技术。围绕本文的主题,本次讨论的重点在于深度学习技术如何有效地取代人工编写的程序代码:

Google的经验是对于大量子系统,其中一些甚至是通过机器学习方式获得的,使用更为通用的端到端机器学习系统取代它们。通常当你有大量复杂的子系统时,必须通过大量复杂代码将它们连接在一起。Google的目标是让大家使用数据和非常简单的算法取代这一切。

机器学习将成为软件工程的敏捷工具

Google研究总监Peter Norvig针对这个话题进行过详细的讨论:用深度学习与可理解性对抗软件工程和验证。他的大致想法如下:

  • 软件。你可以将软件看作为函数构建的规范,而实现相应的函数就可以满足规范的要求。
  • 机器学习。以(x,y)对为例,你会猜测某一函数会使用x作为参数并生成y作为结果,这样就能很好地概括出x这个新值。
  • 深度学习。依然是以(x,y)对为例,可以通过学习知道你所组建的表征(Representation)具备不同级别的抽象,而非简单直接的输入和输出。这样也可以很好地概括出x这个新值。

软件工程师并不需要介入这个循环,只需要将数据流入机器学习组件并流出所需的表征。

表征看起来并不像代码,而是类似这样:

这种全新类型的程序并非人类可以理解的函数分解(Functional decomposition),看起来更像是一堆参数。

在机器学习驱动的编程(MLDP)世界里,依然可以有人类的介入,不过这些人再也不叫“程序员”了,他们更像是数据科学家。

可以通过范例习得程序的部分内容吗?可以。

  • 有一个包含超过 2000 行代码的开源拼写检查软件的例子,这个软件的效果始终不怎么好。但只要通过包含 17 行代码的朴素贝叶斯分类器就能以同样性能实现这个软件的功能,但代码量减少了100倍,效果也变得更好。
  • AlphaGo是另一个例子,该程序的结构是手工编写的,所有参数则是通过学习得到的。

只通过范例可以习得完整的程序吗?简单的程序可以,但大型传统程序目前还不行。

  • 在Jeff Dean的讲话中,他介绍了一些有关使用神经网络进行序列学习的顺序的细节。借助这种方法可以从零开始构建最尖端的机器翻译程序,这将是一种端到端学习获得的完整系统,无需手工编写大量代码或机器学习的模型即可解决一系列细节问题。
  • 另一个例子是学习如何玩Atari出品的游戏,对于大部分游戏机器可以玩得和人一样好,甚至比人玩得更好。如果按照传统方式对不同组件进行长期的规划,效果肯定不会像现在这么好。
  • 神经图灵机(Neural Turing Machine)也是一次学习如何用程序编写更复杂程序的尝试,但Peter认为这种技术不会走的太远。

正如你所期待的,Norvig先生的这次讲话非常棒,很有远见,值得大家一看。

Google正在以开源代码的方式从GitHub收集数据

深度学习需要数据,如果你想要创建一个能通过范例学习如何编程的AI,肯定需要准备大量程序/范例作为学习素材。

目前Google和GitHub已经开始合作让开源数据更可用。他们已经从GitHub Archive将超过3TB的数据集上传至BigQuery,其中包含超过280万个开源GitHub代码库中包含的活动数据,以及超过1.45亿次提交,和超过20亿不同的文件路径。

这些都可以当作很棒的训练数据。

就真的完美无缺吗?

当然不是。神经网络如同“黑匣子”般的本质使其难以与其他技术配合使用,这就像试图将人类潜意识行为与意识行为背后的原因结合在一起一样。

Jeff Dean还提到了Google搜索评级团队在搜索评级研究工作中运用神经网络技术时的犹豫。对于搜索评级,他们想要了解整个模型,了解做出某一决策的原因。当系统出现错误后他们还想了解为什么会出现这样的错误。

为了解决这样的问题,需要创建配套的调试工具,而相关工具必须具备足够的可理解性。

这样的做法会有效的。针对搜索结果提供的机器学习技术RankBrain发布于2015年,现在已成为第三大最重要的搜索评级指标(指标共有100项)。详情可访问:Google将利润丰厚的网页搜索技术交给AI计算机处理

Peter还通过一篇论文《机器学习:技术债的高利率信用卡》进一步介绍了相关问题的更多细节。缺乏明确的抽象层,就算有Bug你也不知道到底在哪。更改任何细节都要改变全局,很难进行纠正,纠正后的结果更是难以预测。反馈环路,机器学习系统生成数据后会将这些数据重新送入系统,导致反馈环路。诱惑性损害(Attractive Nuisance),一旦一个系统使得所有人都想使用,这样的系统很可能根本无法在不同上下文中使用。非稳态(Non-stationarity),随着时间流逝数据会产生变化,因此需要指出到底需要使用哪些数据,但这个问题根本没有明确答案。配置依赖性,数据来自哪里?数据准确吗?其他系统中出现的改动是否会导致这些数据产生变化,以至于今天看到的结果和昨天不一样?训练用数据和生产用数据是否不同?系统加载时是否丢弃了某些数据?缺乏工具,标准化软件开发有很多优秀的工具可以使用,但机器学习编程是全新的,暂时还没有工具可用。

MLDP是未来吗?

这并不是一篇“天呐,世界末日到了”这样的文章,而是一篇类似于“有些事你可能没听说过,世界又将为此产生变化,这多酷啊”的文章。

这种技术依然处于非常早期的阶段。对程序的部分内容进行学习目前已经是可行的,而对大规模复杂程序进行学习目前还不实用。但是当我们看到标题类似于Google如何将自己重塑为一家“机器学习为先”的公司这样的文章,可能还不明白这到底真正意味着什么。这种技术不仅仅是为了开发类似AlphaGo这样的系统,最终结果远比这个还要深刻。

相关文章

查看英文原文Machine Learning Driven Programming: A New Programming for a New World

from:http://www.infoq.com/cn/articles/machine-learning-programing

机器学习&深度学习研究者最重要的11张速查表

作者 Kailash Ahirwar 在 Github 上建立了一个代码速查表,对机器学习初学者来说是不可多得的一个资源。机器之心将文章中的高清图片下载到了百度网盘,读者可从中浏览。也可以点击这里查阅 Medium 上的原文。

对于初学者来讲,入门机器学习和深度学习非常困难;同时深度学习库也难以理解。通过收集多方资源,我在 Github 上创建了一个速查表库,希望能对你有所帮助。欢迎访问这个库,并完善它(如果你也有速查表)。

1.Keras

Keras 是一个非常强大且容易上手的深度学习库;当 Keras 接入 Theano 和 TensorFlow 时,后两者可提供高水平的神经网络 API 以开发和评估深度学习模型。该速查表可用于 Python 数据科学和机器学习。

1-uEv0-859Tp3GK5ynmoLq5w(1).jpeg

2.Numpy

Numpy 库是 Python 中科学性计算的核心库,它提供高性能、多维度的数组对象,以及对这些数组进行运算的工具。该速查表可用于 Python 数据科学和机器学习。

1-o_CO_8Plpi2Ac3s-Gs5IQg(1).png

3.Pandas

这张 Pandas 速查表主要用于数据整理(data wrangling)。

Pandas 库构建在 NumPy 上,并为 Python 编程语言提供易于上手的数据结构和数据分析工具。该速查表可用于 Python 数据科学和机器学习。

1-YhTbz8b8Svi22wNVvqzneg(1).jpeg

1-3-mTHM3ejorJwLnjuIpVNQ(1).jpeg

1-2RJpJMci8ysUbrFOCzPKAw(1).png

4.SciPy

SciPy 库是科学性计算的核心包之一,科学性计算可提供数学算法和构建在 Python 的 NumPy 扩展上的便捷函数 (Convenience Functions) ;该表中还包括线性代数的部分。该速查表可用于 Python 数据科学和机器学习。

1-9gFze6fk9EHcm1bgJsmgFA(1).png

5.Matplotlib

Matplotlib 是一个 Python 2D 绘图库,它在平台上以多种硬拷贝格式和交互环境生成发表品质的图。该速查表用于 Python 数据科学。

1-ykxp7OpgBXbRRHgjzSkeCA(1).png

6.Scikit-learn

Scikit-learn 是一个开源 Python 库,通过统一接口实现一系列的机器学习、预处理、交叉验证和视觉化算法。该速查表可用于 Python 数据科学和机器学习。

1-uEv0-859Tp3GK5ynmoLq5w(1).jpeg

7.Neural Networks Zoo(神经网络大全)

该速查表几乎涵盖了所有类型的神经网络。

1-gccuMDV8fXjcvz1RSk4kgQ(1).png

8.ggplot2

ggplot2 基于图形语法,其思想是你可以利用相同的几个组件构建所有的图形:一个数据集、一个几何集(表征数据点的视觉化标记)和一个协作系统。该速查表用于数据可视化。

1-GOqZNLbHU_d1rZ5qP5RuTQ(1).jpeg

1-kHi0M3FgxGs4CtUW4Rsm-w(1).jpeg

from:http://www.jiqizhixin.com/article/3004