机器学习-李宏毅| keras demo | python

利用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

1
model=Sequential()

添加第一个hidden layer,  Dense意思为添加一个全连接网络,Con2d表示添加一个convolution layer卷积层,input_dim表示输入维度,units表示hidden layer的神经元个数,activation表示激活函数,可以为relu,sigmoid,tanh,softmax,hard_sigmoid,linear等

1
model.add(Dense(input_dim=28*28,units=500,activation='relu'))

再添加一个layer

1
model.add(Dense(units=500,activation='relu'))

最后的输出层,由于是数字识别一共10个数字,所以output是10维,units=10,激活函数选择softmax

1
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。

1
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。

1
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
    1
    2
    3
    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
    1
    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} 键值对。

1
2
3
4
5
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

示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
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%
在这里插入图片描述