理论和代码-CNN

CNN和DNN相比,CNN是若干卷积层以及最后的全连接层和输出层组成,卷积层从某种程度是取代DNN中的隐藏层中的全连接层,减少训练的参数。

CNN的要点有:
1,某些特征,只用关注局部即可,不用关注全局,即是卷积conolutional,以及卷积移动
2,同样的高维度特征,可以在图像的不同位置出现,但可以共享特征,也就是共用卷积核
3,图像部分采样,放大/缩小,不影响对图像识别的判断,即是池化pooling
*,符合这个理论范畴的,不一定是图像,文本/语音都可以用CNN处理,根据不同情况设置不同的卷积内核和卷积移动方向

下面基于keras 手写图像识别

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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import os

import numpy as np
import random
import keras
import matplotlib.pyplot as plt

from keras.datasets import mnist
from keras.layers import Flatten
from keras.layers.convolutional import Conv2D
from keras.layers.convolutional import MaxPooling2D
from keras.layers.core import Dense, Dropout, Activation
from keras.models import Sequential, Model
from keras.optimizers import RMSprop, SGD, Adam
from keras.utils import np_utils

(x_train, y_train), (x_test, y_test) = mnist.load_data()
print(x_train.shape, y_train.shape)
print(x_test.shape, y_test.shape)

x_train = x_train.reshape(x_train.shape[0], 28, 28, 1)
x_train = x_train.astype('float32')
x_test = x_test.reshape(x_test.shape[0], 28, 28, 1)
x_test = x_test.astype('float32')

# normalization to [0, 1]
x_train = x_train / 255
x_test = x_test / 255

# specify the class label
#batch_size = 128
batch_size = 256
number_epochs = 2

# convert class vectors to one-hot vector
y_train = np_utils.to_categorical(y_train, num_classes=10)
y_test = np_utils.to_categorical(y_test, num_classes=10)

# model definition
model = Sequential()

# hidden layer, 1st cnn layer
#model.add(Conv2D(filters=32, kernel_size=(3, 3), input_shape=(28, 28, 1), activation='relu', padding='Same'))
model.add(Conv2D(filters=16, kernel_size=(3, 3), input_shape=(28, 28, 1), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.2))
# hidden layer, 2st cnn layer
#model.add(Conv2D(filters=64, kernel_size=(3, 3), activation='relu', padding='Same'))
model.add(Conv2D(filters=8, kernel_size=(3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.2))
# flatten
model.add(Flatten())
# hidden layer, fully-connected layer
#model.add(Dense(units=128))
model.add(Dense(units=32))
model.add(Activation('relu'))
model.add(Dropout(0.2))
# output layer
model.add(Dense(units=10))
model.add(Activation('softmax'))

# print the model summary
model.summary()

# start compilation
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

# start training
history = model.fit(x_train, y_train, epochs=number_epochs, batch_size=batch_size)

# print the history
print('model params: ', history.params)

# start evaluation
evl_result = model.evaluate(x_test, y_test)
print(model.metrics_names[0], ':', evl_result[0], model.metrics_names[1], ':', evl_result[1])

# select one pic fro previewing
x_test_0 = x_test[0, :].reshape(1, 28, 28, 1)
y_test_0 = y_test[0, :]
plt.imshow(x_test_0.reshape(28, 28))
plt.show()

# start prediction
prediction = model.predict(x_test_0[:])
print('truth :', np.argmax(y_test_0), 'prediction :', prediction[0], 'dnn predict :', np.argmax(prediction[0]))

效果如下

1
2
3
4
5
6
7
Epoch 1/2
60000/60000 [==============================] - 13s 214us/step - loss: 0.9967 - acc: 0.6667
Epoch 2/2
60000/60000 [==============================] - 12s 208us/step - loss: 0.3507 - acc: 0.8885
('model params: ', {'metrics': ['loss', 'acc'], 'samples': 60000, 'batch_size': 256, 'epochs': 2, 'steps': None, 'do_validation': False, 'verbose': 1})
10000/10000 [==============================] - 1s 82us/step
('loss', ':', 0.14500811599269509, 'acc', ':', 0.959)

坚持原创技术分享,您的支持将鼓励我继续创作!