利用keras实现手写数字辨识
首先要建一个Network scratch,input是28∗28
的dimension,其实就是说这是一张image,image的解析度是28∗28
,把它拉成长度是28∗28
维的向量。output呢?现在做的是手写数字辨识,所以要决定它是0-9的哪个数字,output就是每一维对应的数字,所以output就是10维。中间假设你要两个layer,每个layer有500个hidden neuro
创建一个network
model=Sequential()
添加第一个hidden layer, Dense意思为添加一个全连接网络,Con2d表示添加一个convolution layer卷积层,input_dim表示输入维度,units表示hidden layer的神经元个数,activation表示激活函数,可以为relu,sigmoid,tanh,softmax,hard_sigmoid,linear等
model.add(Dense(input_dim=28*28,units=500,activation='relu'))
再添加一个layer
model.add(Dense(units=500,activation='relu'))
最后的输出层,由于是数字识别一共10个数字,所以output是10维,units=10,激活函数选择softmax
model.add(Dense(units=10,activation='softmax'))
configuration配置
需要定义loss function,选择optimizer,以及评估指标metrics,其实所有的optimizer都是Gradent descent based,只是有不同的方法来决定learning rate,比如Adam,SGD,RMSprop,Adagrad,Adalta,Adamax ,Nadam等,configuration完成之后就可以开始train创建的Network。
model.compile(loss='categorical crossentropy',optimizer='adam',metrics=['accuracy'])
pick the best function
model.fit方法,开始用Gradent Descent帮你去train你的Network,那么你要给它你的train_data input 和label,这里x_train代表image,y_train代表image的label,关于x_train和y_train的格式,你都要存成numpy array。
model.fit(x_train,y_train,batch_size=100,epochs=20)
使用模型
接下来要拿train的network来使用,使用有两个不同的情景,这两个不同的情景一个是evaluation,意思就是说你的model在test data 上到底表现得怎样,call evaluate这个函数,然后把x_test,y_test喂给它,就会自动给你计算出Accuracy。它会output一个二维的向量,第一个维度代表了在test set上loss,第二个维度代表了在test set上的accuracy,这两个值是不一样的。loss可能用cross_entropy,Accuraccy是对与不对,即正确率。
- case 1
score = model.evaluate(x_test,y_test)
print('Total loss on Testiong Set : ',score[0])
print('Accuracy of Testiong Set : ',score[1])
第二种是做predict,就是系统上线后,没有正确答案的,call predict进行预测
- case 2
result = model.predict(x_test)
快速理解epoch、iteration和batch
假设有1000个训练样本,batch_size=20,则iteration就是50,将所有的训练样本在同一个模型中训练5遍
batch_size * iteration = 样本数量,epoch=5.
所有样本完成一次前向传播+反向传播为一个epoch
batchsize:简单点说,就是我们一次要将多少个数据扔进模型去训练,这个值介于1和训练样本总个数之间。
iteration:迭代的次数(向模型中扔数据的次数),一个迭代= 同一批batchsize数据的一个正向通过+一个反向通过。
Epoch: 训练集中的全部样本都在训练模型中走了一遍,并返回一次(有去有回),为一个epoch。
由于这个例子中需要使用MNIST数据集,给出的源码中使用(x_train, y_train), (x_test, y_test) = mnist.load_data() 下载数据集,但是过程中需要翻墙,故我在此先将MNIST数据集的包下载下来,然后稍微修改下代码,完成数据的import.其中,numpy.load() 函数可以读取 .npy .npz 等文件类型,并返回对应的数据类型。
1)如果文件类型是 .pny 则返回一个1维数组。
2)如果文件类型是 .npz 则返回一个类似字典的数据类型,包含 {filename: array} 键值对。
path = 'C:\\Users\\Administrator\\Desktop\\mnist.npz'
f = np.load(path)
x_train, y_train = f['x_train'], f['y_train']
x_test, y_test = f['x_test'], f['y_test']
f.close()
下载地址:mnist数据集
提取码:gyt8
示例代码
import numpy as np
from keras.models import Sequential
from keras.layers.core import Dense,Dropout,Activation
from keras.optimizers import SGD,Adam
from keras.utils import np_utils
from keras.datasets import mnist
def load_data():
path = 'C:\\Users\\Administrator\\Desktop\\mnist.npz'
f = np.load(path)
x_train, y_train = f['x_train'], f['y_train']
x_test, y_test = f['x_test'], f['y_test']
f.close()
number=10000
x_train=x_train[0:number]
y_train=y_train[0:number]
x_train=x_train.reshape(number,28*28)
x_test=x_test.reshape(x_test.shape[0],28*28)
x_train=x_train.astype('float32')
x_test=x_test.astype('float32')
y_train=np_utils.to_categorical(y_train,10)
y_test=np_utils.to_categorical(y_test,10)
x_train=x_train
x_test=x_test
x_train=x_train/255
x_test=x_test/255
return (x_train,y_train),(x_test,y_test)
(x_train,y_train),(x_test,y_test)=load_data() #载入数据
model=Sequential()
model.add(Dense(input_dim=28*28,units=633,activation='sigmoid')) #维度28*28,激活函数为sigmoid
model.add(Dense(units=633,activation='sigmoid'))
model.add(Dense(units=633,activation='sigmoid'))
for i in range(10):
model.add(Dense(units=689,activation='sigmoid'))
model.add(Dense(units=10,activation='softmax')) #输出层一定要是10维,units=10;
model.compile(loss='mse',optimizer=SGD(lr=0.1),metrics=['accuracy']) #config
model.fit(x_train,y_train,batch_size=100,epochs=20)
result= model.evaluate(x_test,y_test)
print('\nTEST ACC:',result[1])
添加10层,发现结果还是11%的accuracy
首先先看你在train data的performer,如果它在train data上做得好,那么可能是过拟合,如果在train data上做得不好,怎么能让它做到举一反三呢。所以至少先让它在train data 上得到好的结果。
由得到的结果发现train data acc 也是差的,就说明train没有train好,并不是overfiting过拟合。
接下来进行调参过程:
MSE均方误差不适合于分类问题,将loss function改为categorical_crossentropy,看看结果如何:
发现一换成交叉熵categorical_crossentropy,在train set上的结果就变得很好了。得到86.21%的正确率。
activation function
把sigmoid都改为relu,发现在train的accuracy就爬起来了,train的acc已经将近100分了,test 上也可以得到95.45%