运用tensorflow改写《机器学习与实战》一书中的手写识别系统

来源:互联网 发布:大数据平台发展趋势 编辑:程序博客网 时间:2024/05/16 00:36

最近想入坑机器学习,同时在看《机器学习与实战》一书以及Tensorflow的官方中文文档,发现可以用Tensorflow改写一些书中的示例代码,有的甚至只需要改变一些参数即可,因此决定动手实践一下。由于Tensorflow的文档里面提到了一个叫做MNIST的手写识别数据集,而《机器学习与实战》一书中正好也有一个用KNN算法实现的手写识别系统,因此我首先选择了用Tensorflow改写一下这个系统。

这个系统的数据集是一张张 32*32 像素的图片,图片经过了二值化,因此像素点的取值只有0和1。首先需要把图片变换成一个 1*1024 的

numpy数组,这个函数在《机器学习与实战》附送的源代码的相关章节中已经实现了,我只是把它搬运到了我的模块里面:

def img2vector(filename):    returnVect = zeros((1,1024))    fr = open(filename)    for i in range(32):        lineStr = fr.readline()        for j in range(32):            returnVect[0,32*i+j] = int(lineStr[j])    return returnVect

然后需要批量把训练和测试的图片转成numpy数组,同时把它们对应的标签(即0~9)也转为numpy数组,最后进行序列化方便随后使用。训练

和测试的图片在《机器学习与实战》附送的源代码里面可以获取到,我在文末也会提供,每张图片对应的标签由它的文件名提供,=。相关函数

如下:

#持久化训练集和测试集def storeVector():    trainingFileList = listdir('trainingDigits')    m = len(trainingFileList)    trainingMat = zeros((m, 1024))    hwLabels = zeros((m, 10))    for i in range(m):        fileNameStr = trainingFileList[i]        fileStr = fileNameStr.split('.')[0]     #take off .txt        classNumStr = int(fileStr.split('_')[0])        trainingMat[i,:] = img2vector('trainingDigits/%s' % fileNameStr)        hwLabels[i, classNumStr] = 1    #序列化训练集    f = open('trainX', 'wb')    pickle.dump(trainingMat, f)    f.close()    #序列化训练集标签    f = open('trainY', 'wb')    pickle.dump(hwLabels, f)    f.close()    testFileList = listdir('testDigits')    mTest = len(testFileList)    testMat = zeros((mTest, 1024))    testLabels = zeros((mTest, 10))    for i in range(mTest):        fileNameStr = testFileList[i]        fileStr = fileNameStr.split('.')[0]  # take off .txt        classNumStr = int(fileStr.split('_')[0])        testMat[i, :] = img2vector('testDigits/%s' % fileNameStr)        testLabels[i, classNumStr] = 1    #序列化测试集    f = open('testX', 'wb')    pickle.dump(testMat, f)    f.close()    #序列化测试集标签    f = open('testY', 'wb')    pickle.dump(testLabels, f)    f.close()#读取训练数据和测试数据def getData():    f = open('testX')    testX = pickle.load(f)    f.close()    f = open('testY')    testY = pickle.load(f)    f.close()    f = open('trainX')    trainX = pickle.load(f)    f.close()    f = open('trainY')    trainY = pickle.load(f)    f.close()    return trainX, trainY, testX, testYtrainX, trainY, testX, testY = getData()

需要指出的是,每个样本对应的标签是以"one-hot vector"的形式存储的,即如果一个样本对应的数字为2,则它的标签是(0,0,1,0,0,0,0,0,0,0),即只有

对应位为1,其余位均为0.

接下来需要定义一个随机获取训练子集的函数,以供随后的模型训练:

def next_batch(count):    trainLen = shape(trainX)[0]    if count > trainLen:        print '没有足够的训练数据供随机抽取'        return    returnListIndex = rand.sample(range(trainLen), count)    returnListX = zeros((count, 1024))    returnListY = zeros((count, 10))    for i in range(count):        returnListX[i,:] = trainX[returnListIndex[i], :]        returnListY[i,:] = trainY[returnListIndex[i], :]    return returnListX, returnListY


接下来便是使用tensorflow进行模型的构建、训练和测试的过程了,这个我仅仅是把从tensorflow官方文档上的相关代码copy下来,把训练和测试数据

换为了我自己的,然后调整了一下几个参数而已,代码如下:

if __name__ == '__main__':    x = tf.placeholder(tf.float32, [None, 1024])    # 权重值    W = tf.Variable(tf.zeros([1024, 10]))    # 偏置量    b = tf.Variable(tf.zeros([10]))    # 计算输出    y = tf.nn.softmax(tf.matmul(x, W) + b)    # 占位符用于输入正确值    y_ = tf.placeholder("float", [None, 10])    # 计算交叉熵    cross_entropy = -tf.reduce_sum(y_ * tf.log(y))    # 使用梯度下降算法以0.01的学习速率最小化交叉熵    train_step = tf.train.GradientDescentOptimizer(0.001).minimize(cross_entropy)    # 初始化变量    init = tf.global_variables_initializer()    # 创建会话并且初始化变量    sess = tf.Session()    sess.run(init)    # 开始训练模型    for i in range(1000):        batch_xs, batch_ys = next_batch(100)        sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})    # 评估模型    correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))    # 将布尔数组转换为浮点数并取平均值来确定正确预测项的比例    accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))    # 打印所学习到的模型在测试数据集上面的正确率    print sess.run(accuracy, feed_dict={x: testX, y_: testY})

代码上都有比较详尽的注释,以上代码调用了tensorflow的梯度下降算法,我仅仅修改了算法的步长参数,对tensorflow框架感兴趣的朋友

可以去极客学院学习一下该框架的官方中文文档,地址:http://wiki.jikexueyuan.com/project/tensorflow-zh/tutorials/mnist_beginners.html。

算法的正确率为97%左右,而原书中使用KNN算法的正确率也是这么多。

下面附上文中用到的文件资源链接:

http://download.csdn.net/download/qq_33534383/10155187

解压缩该文件夹,里面的 kNN.py 模块是《机器学习与实战》中使用KNN算法实现手写识别系统的源码,运行该模块的handwritingClassTest函数便能看到测试结果。

tensorForDigits.py 模块是使用Tensorflow实现的手写识别系统,使用命令 python tensorForDigits.py 即可得到测试正确率。


阅读全文
0 0
原创粉丝点击