深度学习的“Hello World”,Mnist手写体数字识别

手写体数字识别这个问题,网上相关的博客很多了,大多的教程和深度学习的书里面,特别是以tensorflow作为工具,这个例子总是最容易提到的。特别的Mnist是tensorflow的官方教程。所以可以参考的比较多。例如下面的官方的github和教程。可以帮你解决一些bug。

tensorflow,Mnist官方教程tensorflow,

Mnist官方github代码

  1. 数据集的准备

官方的教程是直接调用了自带的例子如下,不过运行后发现,官方将不再支持这样的操作,会在之后的版本移除,而且运行起来非常慢。仔细查看源码后发现,里面需要在某个网址下载数据集并解压,而这个网址下载速度很慢。

from tensorflow.examples.tutorials.mnist import input_data
mnist = inpiut_data.read_data_sets("MNIST_data",one_hot=True)

所以就先去这个网址下载了数据集。http://yann.lecun.com/exdb/mnist/,可以仔细阅读网站的数据说明,考虑如何将数据提取出来。有两种方法,第一种,直接利用官方的代码,修改其中下载的函数,将下载的数据直接导入。第二种,自己提取代码。

这里介绍一下第二种:参考https://www.jianshu.com/p/84f72791806f,里面介绍了提取的方法和代码。如果需要可以加上onehot的转换函数:

def int2onehot(array):
    m = len(array)
    maxnum = np.max(array)
    array_onehot = np.zeros((m,maxnum+1)).astype(np.int16)
    for i in range(m):
        array_onehot[i,array[i]] = 1
    return array_onehot

还有onehot转换为int的函数,如果为了显示方便:

def onehot2int(array_onehot):
    array = np.argwhere(array_onehot == 1)[:,1]
    return array

 可以对数据进行归一化,图片数据在[0,255],给所有数据除以255。

2. softmax regression模型建立

模型主要是

                                                                  y_{pred} = softmax(W * X + b)

# 输入占位
x = tf.placeholder(tf.float32,[None, 784])
y = tf.placeholder(tf.int32,[None,10])
# 变量定义
w = tf.Variable(tf.random_normal([784, 10]))
b = tf.Variable(tf.zeros([10]))
# 模型定义
Ylogits =tf.matmul(x,w) + b
y_pred = tf.nn.softmax(Ylogits)
# 损失函数
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=Ylogits, labels=y)) * 100
# 计算预测精度
corr = tf.equal(tf.argmax(y,1),tf.argmax(y_pred,1))
acc = tf.reduce_mean(tf.cast(corr,tf.float32))

需要注意的一点是函数tf.nn.softmax_cross_entropy_with_logits的参数:logits应该是未经过softmax层的。否则结果会不正确,但是不会报错,训练起来,loss不会下降。

3.训练

首先是训练的定义,初始化变量,如果有的话,可以导入之前训练过的权重。在每个epoch中,对训练样本进行了随机打乱,经过测试好像没什么作用。一般经过2000个epoch会到92%的精度。

# 训练定义
train = tf.train.GradientDescentOptimizer(learning_rate=0.005).minimize(loss)
# 初始化变量
init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init)
# 导入权重,如果没有可以注释掉
save_file = './models/1000_0.91100013.ckpt'
tf.train.Saver().restore(sess,save_path=save_file)
print('load weight')
# 训练epochNum个epoch
for k in range(epochNum):
    total_loss = 0
    permutation = np.random.permutation(train_images.shape[0])
    shu_image = train_images[permutation,:]
    shu_label = train_labels[permutation,:]
    for i in range(batchNum):
        batch_x, batch_y = shu_image[i * batchSize:(i + 1) * batchSize - 1, :], shu_label[i * batchSize:(i + 1) * batchSize - 1,:]
        _, loss_value, acc_train = sess.run([train, loss, acc], feed_dict={x: batch_x, y: batch_y})
        total_loss += loss_value
    if k % 100 == 0:
        acc_test = sess.run(acc, feed_dict={x: test_x, y: test_y})
        print('step: {}, train_loss: {:f},train_acc:{:f},test_acc:{:f}'.format(k, total_loss / batchNum, acc_train, acc_test))
        save_file = './models/' + str(k) + '_' + str(acc_test) + '.ckpt'
        tf.train.Saver().save(sess, save_path=save_file)
        print('saved')
sess.close()

 经过测试,GPU对这个例子的加速并不明显,可能是网络比较简单的缘故。

如果达不到92%的精度,可以试着修改lr(learning rate)的值,一般推荐0.001-0.1,每次按照0.001,0.003,0.006,0.01的取值来取值。这是lr=0.005训练了200个epoch的精度。

step: 0, train_loss: 195.986677,train_acc:0.815686,test_acc:0.779000
saved
step: 100, train_loss: 25.366962,train_acc:0.952941,test_acc:0.913000
saved
step: 200, train_loss: 23.749884,train_acc:0.945098,test_acc:0.915000
saved

这就完成了tensorflow的第一次实践喽。

同时给出在keras下实现的代码,简单很多。

from input_data import getdata
from keras.models import Sequential
from keras.layers import Dense, Activation
from keras.optimizers import SGD

train_images,train_labels,test_images,test_labels = getdata(onehot = True)
print(train_images.shape, train_labels.shape)
print(test_images.shape, test_labels.shape)
test_x,test_y = test_images[0:1000,:],test_labels[0:1000,:]

model = Sequential()
model.add(Dense(units=10, input_dim=784))
model.add(Activation("softmax"))
sgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='categorical_crossentropy',optimizer=sgd, metrics=['accuracy'])
model.load_weights('weight.h5')
model.fit(train_images, train_labels, batch_size=256, nb_epoch=10, shuffle=True, verbose=1, validation_split=0.3)
score = model.evaluate(test_images, test_labels, batch_size=256,verbose=1)
model.save_weights('weight2.h5')
print(score)

猜你喜欢

转载自blog.csdn.net/Leon_zyz/article/details/82586682
今日推荐