#!/usr/bin/env python
# coding: utf-8
19.2 深度学习的概念及关键技术
1、神经网络模型
·生物神经元
·轴突(输出)终端为其他神经元的树突(输入)
·人工神经网络
2、深度学习之卷积神经网络
·深度学习结构:含有多隐层的神经网络。
·池化:子采样,可看作一种特殊的卷积过程。
·激活函数:sigmoid、tanh、relu
·sigmoid:把一个实数压缩至0~1(分类的概率)
·relu:对于随机梯度下降的收敛有巨大的加速作用。
但脆弱,易造成不可逆转的死亡。
·卷积神经网络的网络结构
若干卷积层(配合relu) + 池化层 + 全连接层(分类器的作用)
19.3 Python深度学习库——Keras
1、Keras的安装
import numpy,scipy
# In[ ]:
import tensorflow as tf
# In[ ]:
import keras
2、Keras的网络层
(包括:常用层、卷积层、池化层、局部连接层、递归层、嵌入层、高级激活层、规范层、噪声层、包装层,自己编写的层)
·二维卷积层
·Dense层(全连接层)
3、用Keras构建神经网络
步骤:
1、选择模型
2、构建网络层
3、编译
4、训练
5、预测
19.4 程序设计的思路
数据集的描述:
·训练与测试数据:28*28像素
·训练数据集:测试数据集 = 60000 : 10000
·输出层:十个神经元
网络结构:
·输入层:原始训练图像
·第一卷积层:6个5*5的卷积核,步长为1
·第一池化层:2*2的卷积核,步长为2的最大池化
·第一卷积层:12个5*5的卷积核,步长为1
·第一池化层:2*2的卷积核,步长为2的最大池化
·输出层:十维向量,激活函数为sigmoid
代码流程简述:
(1)获取训练数据 和 测试数据
(2)训练网络的超参数的定义(学习率,每次迭代中训练的样本数目,迭代次数)
(3)构建网络层级结构
(4)编译模型
(5)训练模型
(6)网络模型评估
19.5 源代码
1、MNIST数据集
·一个计算机视觉数据集(7包含0000张手写数字的灰度图片)28*28像素点
2、手写体识别案例体现
# 读取MNIST数据集
import numpy as np
# In[ ]:
# 数据加载基类,派生出 图片加载器 和 标签加载器
class Loader(object):
def __init__(self, path, count):
self.path = path
self.count = count
def get_file_count(self):
print(self.path)
f = open(self.path, 'rb')
content = f.read()
f.close()
return content
# In[ ]:
# 图像数据加载器
class ImageLoader(Loader):
# 内部函数,从文件字节数组中获取第index个图像数据
def get_picture(self, content, index):
start = index * 28 * 28 +16
picture = []
for i in range(28):
picture.append([])
for j in range(28):
byte1 = content[start + i*28 + j]
picture[i].append(byte1)
return picture
# 将图像数据转化成长度为784行向量形式
def get_one_sample(self, picture):
sample = []
for i in range(28):
for j in range(28):
sample.append(picture[i][j])
return sample
# 加载数据文件,获得全部样本的输入向量,onerow表示是否将每张图片转化为行向量,to2表示是否转化为0,1矩阵
def load(self, onerow = False):
content = self.get_file_content()
data_set = []
for index in range(self.count):
onepic = self.get_picture(content, index)
if onerow:
onepic = self.get_one_sample(onepic)
data_set.append(onepic)
return data_set
# In[ ]:
# 标签数据加载器
class LabelLoader(Loader):
# 加载数据文件,获得全部样本的标签向量
def load(self):
content = self.get_file_content()
labels = []
for index in range(self.count):
onelabel = content[index + 8]
onelabelvec = self.norm(onelabel)
labels.append(onelabelvec)
return labels
# 内部函数,one-hot编码,用于将一个值转换为10维标签向量
def norm(self, label):
label_vec = []
label_value = label
for i in range(10):
if i == label_value:
label_vec.append(1)
else:
label_vec.append(0)
return label_vec
# 获得训练数据集,onerow表示是否将每张图片转化为行向量
def get_training_data_set(num, onerow = False):
image_loader = ImageLoader('train-images.idx3-ubyte', num)
label_loader = LabelLoader('train-labels.idx1-ubyte', num)
return image_loader(onerow), label_loader.load()
# 获得测试数据集, onerow表示是否将每张图片转化为行向量
def get_test_data_set(num, onerow = False):
image_loader = ImageLoader('t10k-images.idx3-ubyte', num)
label_loader = LabelLoader('t10k-labels.idx1-ubyte', num)
return image_loader.load(onerow), label_loader.load()
# 将个长度为784的行向量打印成图形的样式
def printimg(onepic):
onepic = onepic.reshape(28, 28)
for i in range(28):
for j in range(28):
if onepic[i, j] == 0:
print(' ', end = '')
else:
print('* ', end = '')
print('')
# In[ ]:
# 训练及测试数据集
import numpy as np
np.random.seed(1337)
from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.layers import Conv2D, MaxPooling2D, AveragePooling2D
import MNIST
# In[ ]:
# 全局变量
batch_size = 128 # 批处理样本数量
nb_classes = 10 # 分类数目
epochs = 600 # 迭代次数
img_rows, img_cols = 28, 28 # 输入图片样本的宽、高
nb_filters = 32 # 卷积核的个数
pool_size = (2, 2) # 池化层的大小
kernel_size = (5, 5) # 卷积核的大小
input_shape = (img_rows, img_cols, 1) # 输入图片的维度
# In[ ]:
X_train, Y_train = MNIST.get_test_data_set(6000, False)
X_test, Y_test = MNIST.get_test_data_set(1000, False)
X_train = np.array(X_train).astype(bool).astype(float) / 255 # 数据归一化
X_train = X_train[:,:,:,np.newaxis] # 添加一个通道,代表图片通道
Y_train = np.array(Y_train)
X_test = np.array(X_test).astype(bool).astype(float) / 255 # 数据归一化
X_test = X_test[:,:,:,np.newaxis] # 添加一个通道,代表图片通道
Y_test = np.array(Y_test)
print('样本数据集的维度:', X_train.shape, Y_train.shape)
print('测试数据集的维度:', X_test.shape, Y_test.shape)
# In[ ]:
# 构建模型
model = Sequential()
model.add(Conv2D(6, kernel_size, input_shape=input_shape, strides=1))
model.add(AveragePooling2D(pool_size=pool_size, strides=2))
model.add(Conv2D(12, kernel_size, strides=1))
model.add(AveragePooling2D(pool_size=pool_size, strides=2))
model.add(Flatten()) # 拉成一维度矩阵
model.add(Dense(nb_classes))
model.add(Activation('sigmoid'))
# In[ ]:
# 编译模型
model.compile(loss = 'categorical_crossentropy', optimizer='adadelta', metrics= ['accuracy'])
# In[ ]:
# 训练模型(420最为精确!!)
model.fit(X_train, Y_train, batch_size=batch_size, epochs=epochs, verbose=1, validation_data=(X_test, Y_test))
# In[ ]:
# 评估模型
score = model.evaluate(X_test, Y_test, verbose=0)
print('Test score:', score[0])
print('Trst accuracy:', score[1])
# In[ ]:
# 保存模型!!!
model.save('cnn_model.h5')
3、预测自己手写图像
# In[2]:
from keras.models import load_model
import numpy as np
import cv2
# In[ ]:
model = load_model('cnn_model.h5')
image = cv2.imread('1.png', 0)
img = cv2.imread('1.png', 0)
img = np.reshape(img, (1,28,28,1)).astype(bool).astype('float32')
my_proba = model.predict_proba(img)
my_predict = model.predict_classes(img)
print('识别为:')
print(my_proba * 10**10)
print(my_predict * 10**10)
cv2.imshow('Image1', image)
cv2.waitKey(0)