【机器学习实战(五)】手写数字识别:sklearn包中神经网络库的使用

目录

    1. 神经网络相关知识点回顾
    • 1.1. 感知机:神经网络的最小单元
    • 1.2. 神经网络的学习:BackPropagation算法
      • 1.2.1. 标准BP算法
      • 1.2.2. 累积BP算法
    1. sklearn中神经网络库的简介
    • 2.1. 分类:MLPClassifier
    1. 编程实现

这是《西瓜书带学训练营·实战任务》系列的第五篇笔记

1. 神经网络相关知识点回顾

1.1. 感知机:神经网络的最小单元

神经网络中最基本的成分是神经元(neuron)模型,最常见的模型是M-P神经元模型,也可以称为感知机(Perceptron)

若对生物学有一点基础的了解,就可以知道上面构造的简化的M-P神经元模型几乎完全吻合生物学上的定义:

当前神经元通过与上游神经元之间的突触结构,接受来自上游的神经元1到n传递过来的信号x1,x2...xn,由于不同的上游信号传递过来它们的影响程度是不一样的,因此对它们进行加权求和,即∑wixi,则得到总的上游信号

另外当前神经元还有一个激活阈值θ,若上游信号的汇总信号强度大于θ,即则∑wixi-θ > 0,则当前神经元被激活,处于兴奋状态;若若上游信号的汇总信号强度小于θ,即则∑wixi-θ < 0,则当前神经元未被激活,处于抑制状态

对于生物学上的神经元来说,它只有两个状态:

  • “1”:对应神经元兴奋;
  • “0”:对应神经元抑制;

则它接受的信号为上游神经元的输出为 xi∈{0,1},它的输出信号为 y∈{0,1}

则它的理想激活函数是阶跃函数,即f(x)=sgn(x)

然而,阶跃函数具有不连续、不光滑等不太好的性质,因此实际上常用sigmoid函数作为激活函数

则此时激活函数为f(x)=sigmoid(∑wixi-θ),很明显若选择sigmod函数作为感知机的激活函数,则此时感知机等价于一个logistic回归分类器

类比logistic回归分类器

  • 对于线性可分的分类任务,感知机完全等价于logistic回归分类器

  • 对于线性不可分问题,logistic回归可以构造额外的高阶多项式:

    本质上是将原始特征空间中线性不可分的样本向高维特征空间进行映射,使得它们在新的高维特征空间中线性可分

    而感知器无法进行高维空间的映射,只能基于原始特征空间寻找线性判别边界,因此感知机在面对简单的非线性可分问题是,往往无法得到理想的判别面

感知机的学习规则:

1.2. 神经网络的学习:BackPropagation算法

神经网络的学习算法本质上是数学上常用的梯度下降(Gradient Descend)算法

依据在一轮神经网络的训练过程中所用到的训练样本的数量的不同,可分为以下两类:

  • 标准BP算法:每次网络训练只针对单个训练样本,一次训练就输入一个训练样本,更新一次网络参数;

  • 累积BP算法:每次网络训练只针对所有训练样本,一次将所有训练样本输入,更新一次网络参数;

1.2.1. 标准BP算法

以wh,j为例进行推导

在标准BP算法中,由于只对输入的一个训练样本进行网络参数的训练,因此它的目标函数为当前样本k的均方误差Ek

此时关键在于怎么推出△whj的表达式?

根据链式求导法则,Whj的影响链条为:

因此△whj可以写成:

中间推导过程省略,最后得到的△whj的表达式为:

1.2.2. 累积BP算法

累积BP算法的目标是最小化训练集的累积误差:

这是累积BP算法与标准BP算法的最大的也是最本质的差别

标准BP算法存在的问题:

每次更新只针对单个训练样本,参数更新得非常频繁,而且不同样本训练的效果可能出现相互“抵消”的现象

因此为了达到与累积误差相同的极小点,标准BP算法往往需要进行更多次的迭代

累积BP算法的优缺点:

  • 优点:直接对累积误差最小化,它在读取整个训练样本集D后才对参数进行一次更新,其参数更新的频率低得多

  • 缺点:累积误差下降到一点程度之后,进一步下降会非常缓慢

    此时标准BP算法往往会更快得到较好的解,因为其解的震荡性给它带来了一个好处——容易跳出局部最优

2. sklearn中神经网络库的简介

sklearn中神经网络的实现不适用于大规模数据应用。特别是 scikit-learn 不支持 GPU

2.1. MLPClassifier

神经网络又称为多层感知机(Multi-layer Perceptron,MLP)

sklearn中用MLP进行分类的类为MLPClassifier

主要参数说明:

参数 说明
hidden_​​layer_sizes tuple,length = n_layers - 2,默认值(100,)第i个元素表示第i个隐藏层中的神经元数量。
activation {‘identity’,‘logistic’,‘tanh’,‘relu’},默认’relu’ 隐藏层的激活函数:‘identity’,无操作激活,对实现线性瓶颈很有用,返回f(x)= x;‘logistic’,logistic sigmoid函数,返回f(x)= 1 /(1 + exp(-x));‘tanh’,双曲tan函数,返回f(x)= tanh(x);‘relu’,整流后的线性单位函数,返回f(x)= max(0,x)
slover {‘lbfgs’,‘sgd’,‘adam’},默认’adam’。权重优化的求解器:'lbfgs’是准牛顿方法族的优化器;'sgd’指的是随机梯度下降。'adam’是指由Kingma,Diederik和Jimmy Ba提出的基于随机梯度的优化器。注意:默认解算器“adam”在相对较大的数据集(包含数千个训练样本或更多)方面在训练时间和验证分数方面都能很好地工作。但是,对于小型数据集,“lbfgs”可以更快地收敛并且表现更好。
alpha float,可选,默认为0.0001。L2惩罚(正则化项)参数。
batch_size int,optional,默认’auto’。用于随机优化器的minibatch的大小。如果slover是’lbfgs’,则分类器将不使用minibatch。设置为“auto”时,batch_size = min(200,n_samples)
learning_rate {‘常数’,‘invscaling’,‘自适应’},默认’常数"。 用于权重更新。仅在solver ='sgd’时使用。'constant’是’learning_rate_init’给出的恒定学习率;'invscaling’使用’power_t’的逆缩放指数在每个时间步’t’逐渐降低学习速率learning_rate_, effective_learning_rate = learning_rate_init / pow(t,power_t);只要训练损失不断减少,“adaptive”将学习速率保持为“learning_rate_init”。每当两个连续的时期未能将训练损失减少至少tol,或者如果’early_stopping’开启则未能将验证分数增加至少tol,则将当前学习速率除以5。

MLPClassifier的训练使用BP算法,其使用交叉熵损失函数(Cross-Entropy loss function)

MLP的训练需要准备

  • Xm*n:m个训练样本的n维特征向量构成的特征矩阵

  • Ym:m训练样本的目标值组成的向量

from sklearn.neural_network import MLPClassifier

X = [[0., 0.], [1., 1.]]
y = [0, 1]

# 模型训练
clf = MLPClassifier(solver='lbfgs', alpha=1e-5, hidden_layer_sizes=(5, 2), random_state=1)
clf.fit(X, y)

# 模型预测
clf.predict([[2., 2.], [-1., -2.]])

以上训练好的MLP模型保存在clf对象中,该对象有以下两个子变量:

  • clf.coefs_:模型的一系列权重矩阵

    # 用以下命令查看每一层的权重矩阵的维度
    >>[coef.shape for coef in clf.coefs_]
    [(2, 5), (5, 2), (2, 1)]
    

    其中下标为 i 的权重矩阵表示第 i 层和第 i+1 层之间的权重

  • intercepts_:一系列偏置向量

    其中的下标为 i 的向量表示添加到第 i+1 层的偏置值

  • 多分类任务

    MLPClassifier 通过应用 Softmax 作为输出函数来支持多分类

    softmax回归本质上是将原先常见的二元分类任务神经网络的输出层采用的sigmoid激活函数换成softmax回归

    例如要利用神经网络进行k类的分类,则神经网络结构如下:

    那么最后一层即网络的输出层所采用的激活函数——softmax回归到底长什么样呢?

    本人的手写笔记

    因此该网络的输出层又被称为softmax layer

    因此在提供训练集时,若总共有k的类别,当某一个训练样本的类别为第i类时,它的目标值应该为[0, 0, ..., 1, ..., 0],只在向量的第i个位置标为1,其他位置都为0

  • 多标签分类任务

    一个样本可能属于多个类别。 对于每个类,原始输出经过 logistic 函数变换后,大于或等于 0.5 的值将进为 1,否则为 0。 对于样本的预测输出,值为 1 的索引位置表示该样本的分类类别

    >>> X = [[0., 0.], [1., 1.]]
    >>> y = [[0, 1], [1, 1]]
    >>> clf = MLPClassifier(solver='lbfgs', alpha=1e-5,
    ...                     hidden_layer_sizes=(15,), random_state=1)
    ...
    >>> clf.fit(X, y) 
    
    >>> clf.predict([[1., 2.]])
    array([[1, 1]])
    >>> clf.predict([[0., 0.]])
    array([[0, 1]])
    

3. 编程实现

对于神经网络,要说它的Hello world,莫过于识别手写数字了

首先要获取实验数据,下载地址:http://www.iro.umontreal.ca/~lisa/deep/data/mnist/mnist.pkl.gz

数组中的每一行都表示一个灰度图像。每个元素都表示像素所对应的灰度值。

数据集中将数据分成3类:训练集,验证集,测试集。一般情况下会将训练数据分为训练集和测试集

为什么要将训练数据分为训练集和测试集?

将原始数据分开,保证用于测试的数据是训练模型时从未遇到的数据可以使测试更客观。否则就像学习教课书的知识,又只考教课书的知识,就算不理解记下了就能得高分但遇到新问题就傻眼了。

好一点的做法就是用训练集当课本给他上课,先找出把课本知识掌握好的人,再参加由新题组成的月考即测试集,若是还是得分高,那就是真懂不是死记硬背了。

但这样选出来的模型实际是还是用训练集和测试集共同得到的,再进一步,用训练集和验证集反复训练和检测,得到最好的模型,再用测试集来一局定输赢即期末考试,这样选出来的就更好了。

本实验中为了方便将训练集与验证集合并

  1. 先载入数据,并简单查看一下数据

    from sklearn.neural_network import MLPClassifier
    import numpy as np
    import pickle
    import gzip
    import matplotlib.pyplot as plt
    
    # 加载数据
    with gzip.open(r"mnist.pkl.gz") as fp:
        training_data, valid_data, test_data = pickle.load(fp)
    
    X_training_data, y_training_data = training_data
    X_valid_data, y_valid_data = valid_data
    X_test_data, y_test_data = test_data
    
    # 合并训练集,验证集
    X_training = np.vstack((X_training_data, X_valid_data))
    y_training = np.append(y_training_data, y_valid_data)
    
    def show_data_struct():
        print X_training_data.shape, y_training_data.shape
        print X_valid_data.shape, y_valid_data.shape
        print X_test_data.shape, y_test_data.shape
        print X_training_data[0]
        print y_training_data[0]
    
    show_data_struct()
    
  2. 随便看几张训练图片

    def show_image():
        plt.figure(1)
        for i in range(10):
            image = X_training[i]   # 得到包含第i张图的像素向量,为1*768
            pixels = image.reshape((28, 28)) # 将原始像素向量转换为28*28的像素矩阵
            plt.subplot(5,2,i+1)
            plt.imshow(pixels, cmap='gray')
            plt.title(y_training[i])
            plt.axis('off')
        plt.subplots_adjust(top=0.92, bottom=0.08, left=0.10, right=0.95, hspace=0.45,
                            wspace=0.85)
        plt.show()
    
    show_image()
    
  3. 训练模型

    为了获得比默认参数更佳的模型,我们采用网格搜索法搜索更优的训练超参数,使用gridSearchCV实现,上文3.2.2.2. 调参方法:网格搜索中有较为详细的说明

    from sklearn.model_selection import GridSearchCV
    
    mlp = MLPClassifier()
    mlp_clf__tuned_parameters = {"hidden_layer_sizes": [(100,), (100, 30)],
                                     "solver": ['adam', 'sgd', 'lbfgs'],
                                     "max_iter": [20],
                                     "verbose": [True]
                                     }
    estimator = GridSearchCV(mlp, mlp_clf__tuned_parameters, n_jobs=6)
    estimator.fit(X_training, y_training)
    

参考资料:

(1) 周志华《机器学习:第5章 神经网络》

(2) 吴恩达《deeplearning.ai:改善深层神经网络》

(3) scikit-learn中文网《神经网络模型(有监督)》

(4) 啊噗不是阿婆主《sklearn 神经网络MLPclassifier参数详解》

(5) 多问Why.简书《SkLearn之MLP》

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容

  • 原文地址:http://www.cnblogs.com/subconscious/p/5058741.html 神...
    Albert陈凯阅读 5,421评论 0 48
  • 改进神经网络的学习方法(下) 权重初始化 创建了神经网络后,我们需要进行权重和偏差的初始化。到现在,我们一直是根据...
    nightwish夜愿阅读 1,838评论 0 0
  • 随便哼唱一首歌,或隐晦或直白,情字随着歌声飘; 随便翻看一部剧,或恬淡或浓烈,爱字伴着剧情绕。 “衣带渐宽终不悔,...
    老鼠夹阅读 773评论 2 1
  • 家里来的这个六岁的小男孩是个小机灵鬼,晚上我睡在床边,跟他说,梓晨你今天晚上就睡我们这儿吧,他很开心说好啊...
    Ju_Ju阅读 660评论 0 0
  • 提到教育子女,我觉得我离那些条条杠杠的传统教育不一样,孩子我基本是散养的。平时自由发挥释放天性,在日常生活当中看到...
    饶瞳阅读 382评论 0 1