在本章节中,并不会对神经网络进行介绍,所以若是不了解神经网络的话,强烈推荐先去看《西瓜书》,或者看一下个人上一篇博客:数据挖掘入门系列教程(七点五)之神经网络介绍html
原本是打算按照《Python数据挖掘入门与实践》里面的步骤使用神经网络来识别验证码,可是呢,验证码要本身生成,而后我又想了一下,不是有大名鼎鼎的MNIST数据集吗,为何不使用它呢,他不香吗?python
MNIST(Mixed National Institute of Standards and Technology database)相信你们基本上都了解过他,大部分的机器学习入门项目就是它。它是一个很是庞大的手写数字数据集(官网)。里面包含了0~9的手写的数字。部分数据以下:git
数据集分为两个部分,训练集和测试集。而后在不一样的集合中分为两个文件,数据Images文件和Labels文件。在数据集中一个有60,000个训练数据和10,000个测试数据。图片的大小是28*28。github
万物始于数据集,尽管官网提供了数据集供咱们下载,可是在sklearn中提供了更方便方法让咱们下载数据集。代码以下:算法
import numpy as np from sklearn.datasets import fetch_openml # X为image数据,y为标签 X, y = fetch_openml('mnist_784', version=1, return_X_y=True)
其中X,y中间既包含了训练集又包含了测试集。也就是说X或者y中有70,000条数据。 那么数据是什么呢?api
在X中,每一条数据是一个长为\(28 \times 28=784\)的数组,数组的数据是图片的像素值。每一条y数据就是一个标签,表明这张图片表示哪个数字(从0到9)。数组
而后咱们将数据进行二值化,像素值大于0的置为1,并将数据保存到文件夹中:网络
X[X > 0 ] = 1 np.save("./Data/dataset",X) np.save("./Data/class",y)
而后在Data文件夹中就出现了如下两个文件:框架
咱们取出dataset中间的一条数据,而后转成28*28的格式,以下所示:dom
数据集既可使用上面的方法获得,也能够从个人Github上面进行下载(其中dataset数据集由于GitHub文件大小的限制因此进行了压缩,须要解压才可以使用)。
前面的步骤咱们下载好了数据集,如今咱们就能够来加载数据了。
import numpy as np X = np.load("./Data/dataset.npy") y = np.load("./Data/class.npy")
取出X中的一条数据以下所示:
取出y中的一条数据,以下所示:
一切都很完美,可是这里有一个问题,在神经网络中,输出层其实是这样的:
它并非直接输出某一个结果,而是输出\(y_1,…,y_j,…,y_l\)结果(在MNIST中\(l=10\),由于只有10种数字)。以上面的5为例子,输出层并非单纯的输出只输出一个数字,而是要输出10个值。那么如何将输出5变成输出10个数字呢?这里咱们使用”one hot Encoding“。
One-Hot编码,又称为一位有效编码,主要是采用\(N\)位状态寄存器来对\(N\)个状态进行编码,每一个状态都由他独立的寄存器位,而且在任意时候只有一位有效。
如下面的数据为例,每一行表明一条数据,每一列表明一个属性。其中第2个属性只须要3个状态码,由于他只有0,1,2三种属性。这样咱们就可使用100表明0,010表明1,001表明2。
那么这个数据编码后的数据长什么样呢?以下图:
如今咱们就能够将前面加载的数据集标签\(y\)进行“one hot Encoding”。
代码以下:
from sklearn.preprocessing import OneHotEncoder # False表明不生成稀疏矩阵 onehot = OneHotEncoder(sparse = False) # 首先将y转成行长为7000,列长为1的矩阵,而后再进行转化。 y = onehot.fit_transform(y.reshape(y.shape[0],1))
接着就是切割数据集了。将数据集切割成训练集和测试集。
from sklearn.model_selection import train_test_split x_train,x_test,y_train,y_test = train_test_split(X,y,random_state=14)
在神经网络中,咱们使用pybrain框架去构建一个神经网络。可是呢,对于pybrain库,他很不同凡响,他要使用本身的数据集格式,所以,咱们须要将数据转成它规定的格式。
from pybrain.datasets import SupervisedDataSet train_data = SupervisedDataSet(x_train.shape[1],y.shape[1]) test_data = SupervisedDataSet(x_test.shape[1],y.shape[1]) for i in range(x_train.shape[0]): train_data.addSample(x_train[i],y_train[i]) for i in range(x_test.shape[0]): test_data.addSample(x_test[i],y_test[i])
终于,数据集的加载就到这里结束了。接下来咱们就能够开始构建一个神经网络了。
首先咱们来建立一个神经网络,网络中只含有输入层,输出层和一层隐层。
from pybrain.tools.shortcuts import buildNetwork # X.shape[1]表明属性的个数,100表明隐层中神经元的个数,y.shape[1]表明输出 net = buildNetwork(X.shape[1],100, y.shape[1], bias=True)
这里说有如下“bias”的做用。bias表明的是偏置神经元,bias = True表明偏置神经元激活,也就是在每一层都使用这个这个神经元。偏置神经元以下图,实际上也就是阈值,只不过换一种说法而已。
如今咱们已经构建好了一个比较简单的神经网络,接下来咱们就是使用BP算法去获得合适的权重值了。
具体的算法步骤在上一篇博客已经介绍过了,很幸运的是在pybrain中间提供了BP算法的库供咱们使用。这里就直接上代码吧。关于BackpropTrainer更加细节的使用能够看官网
from pybrain.supervised.trainers import BackpropTrainer trainer = BackpropTrainer(net, train_data, learningrate=0.01,weightdecay=0.01)
这里面有几个参数稍微的说明下:
net:神经网络
train_data:训练的数据集
learningrate:学习率,也就是下面的\(\eta\),一样它可使用lrdecay这个参数去控制衰减率,具体的就去看官网文档吧。
weightdecay:权重衰减,权重衰减也就是下面的\(\lambda\)
而后咱们就能够开始训练了。
trainer.trainEpochs(epochs=100)
epochs
也就是训练集被训练遍历的次数。
接下载即是等待的时间了。等待训练集训练成完成。训练的时间跟训练集的大小,隐层神经元的个数,电脑的性能,步数等等有关。
切记切记,这一次的程序就不要在阿里云的学生机上面跑了,仍是用本身的机器跑吧。尽管联想小新pro13 i5版本性能还能够,可是仍是跑了一个世纪这么久,哎(耽误了我打游戏的时间)。
经过前面的步骤以及等待一段时间后,咱们就完成了模型的训练。而后咱们就可使用测试集进行预测。
predictions = trainer.testOnClassData(dataset=test_data)
predictions
的部分数据,表明着测试集预测的结果:
而后咱们就能够开始验证准确度了,这里继续使用F1评估。这个已经在前面介绍过了,就再也不介绍了。
这里有个地方须要注意,由于以前的y_test
数据咱们使用one-hot encoding
进行了编码,所以咱们须要先将one-hot
编码转成正常的形式。
# 取每一行最大值的索引。 y_test_arry = y_test.argmax(axis =1)
具体效果以下:
而后使用F1
值进行验证。
from sklearn.metrics import f1_score print("F-score: {0:.2f}".format(f1_score(predictions,y_test_arry,average='micro')))
而后结果以下:
结果只能说还行吧,不是特别的差,可是也不是特别的好。
项目地址:Github。尽管上面的准确度不咋地,只有\(86\%\),可是也还行吧,毕竟也是使用了一层隐层,而后隐层也只有100个神经元。
若是电脑的性能不够的话,但是适当的减小步数和训练集的大小,以及隐层神经元的个数。