在此文件中,我们提供给你了一个模板,以便于你根据项目的要求一步步实现要求的功能,进而完成整个项目。如果你认为需要导入另外的一些代码,请确保你正确导入了他们,并且包含在你的提交文件中。以'练习'开始的标题表示接下来你将开始实现你的项目。注意有一些练习是可选的,并且用'可选'标记出来了。
在此文件中,有些示例代码已经提供给你,但你还需要实现更多的功能让项目成功运行。除非有明确要求,你无须修改任何已给出的代码。以'练习'开始的标题表示接下来的代码部分中有你必须要实现的功能。每一部分都会有详细的指导,需要实现的部分也会在注释中以'TODO'标出。请仔细阅读所有的提示!
除了实现代码外,你还必须回答一些与项目和你的实现有关的问题。每一个需要你回答的问题都会以'问题 X'为标题。请仔细阅读每个问题,并且在问题后的'回答'文字框中写出完整的答案。我们将根据你对问题的回答和撰写代码所实现的功能来对你提交的项目进行评分。
注意: Code 和 Markdown 区域可通过 Shift + Enter 快捷键运行。此外,Markdown可以通过双击进入编辑模式。
你可以通过连接MNIST的字符来合成数据来训练这个模型。为了快速导入数据集,我们可以使用 Keras Datasets 中文文档。
In [1]:
from keras.datasets import mnist
(X_raw, y_raw), (X_raw_test, y_raw_test) = mnist.load_data()
n_train, n_test = X_raw.shape[0], X_raw_test.shape[0]
In [2]:
import matplotlib.pyplot as plt
import random
%matplotlib inline
%config InlineBackend.figure_format = 'retina'
for i in range(15):
plt.subplot(3, 5, i+1)
index = random.randint(0, n_train-1)
plt.title(str(y_raw[index]))
plt.imshow(X_raw[index], cmap='gray')
plt.axis('off')
In [3]:
import numpy as np
n_class, n_len, width, height = 11, 5, 28, 28
def generate_dataset(X, y):
X_len = X.shape[0]
X_gen = np.zeros((X_len, height, width*n_len, 1), dtype=np.uint8)
y_gen = [np.zeros((X_len, n_class), dtype=np.uint8) for i in range(n_len)]
# 随机取1~5个数字,并拼接成新的图片
for i in range(X_len):
for j in range(5):
# 这里给定一个概率让空白取代数字
if 4 < random.randint(0,6):
y_gen[j][i][10] = 1
else:
index = random.randint(0, X_len-1)
X_gen[i,:,j*width:(j+1)*width, 0] = X[index]
y_gen[j][i][y[index]] = 1
return X_gen, y_gen
X_train, y_train = generate_dataset(X_raw, y_raw)
X_test, y_test = generate_dataset(X_raw_test, y_raw_test)
print(y_train[0].shape)
In [5]:
# 显示生成的图片
for i in range(15):
plt.subplot(5, 3, i+1)
index = random.randint(0, n_test-1)
title = ''
for j in range(n_len):
title += str(np.argmax(y_test[j][index])) + ','
plt.title(title)
plt.imshow(X_test[index][:,:,0], cmap='gray')
plt.axis('off')
设计并实现一个能够识别数字序列的深度学习模型。为了产生用于测试的合成数字序列,你可以进行如下的设置:比如,你可以限制一个数据序列最多五个数字,并在你的深度网络上使用五个分类器。同时,你有必要准备一个额外的“空白”的字符,以处理相对较短的数字序列。
在思考这个问题的时候有很多方面可以考虑:
在使用 Keras 搭建模型的时候,你可以使用 泛型模型 的方式来搭建多输出模型。
In [4]:
# 导入所需的模型
from keras.layers import Convolution2D
from keras.layers import MaxPooling2D
from keras.layers import Flatten
from keras.layers import Dense
from keras.layers.core import Dropout
from keras.optimizers import SGD
from keras.models import Model
from keras.layers import Input, Dense
In [ ]:
def train_model(X_train, y_train):
main_input = Input(shape=(28, 140, 1), name='main_input')
# 卷积层
x = Convolution2D(32, 3, 3, activation="relu")(main_input)
x = MaxPooling2D(pool_size = (2, 2))(x)
x = Convolution2D(32, 3, 3, activation="relu")(x)
x = MaxPooling2D(pool_size=(2, 2))(x)
x = Convolution2D(32, 3, 3 ,activation="relu")(x)
x = Convolution2D(32, 3, 3, activation="relu")(x)
x = Flatten()(x)
x = Dropout(0.3)(x)
# 分别训练5个数字
y_out = [Dense(11, activation='softmax')(x) for i in range(n_len)]
# 使用泛型输出5个数字的序列
model = Model(input=main_input, output=y_out)
model.compile(optimizer='rmsprop', loss="categorical_crossentropy", metrics=["accuracy"])
model.fit(X_train, y_train, batch_size=1024, nb_epoch=8, shuffle=True, verbose=1, validation_split=0.2)
return model
model = train_model(X_train, y_train)
你为解决这个问题采取了什么技术?请详细介绍你使用的技术。
回答:
In [26]:
from keras.utils.visualize_util import plot, model_to_dot
from IPython.display import Image, SVG
# 可视化网络模型
SVG(model_to_dot(model, show_shapes=True).create(prog='dot', format='svg'))
Out[26]:
In [8]:
# 测试模型
prediction = model.predict(X_test)
In [9]:
# 计算测试集中数字序列的准确率
def evaluate(model):
right = 0
error = 0
for i in range (1000):
right_num = 0
for j in range(5):
y_pred_num = np.argmax(prediction[j][i])
y_test_num = np.argmax(y_test[j][i])
if y_pred_num == y_test_num:
right_num += 1
if right_num == 5:
right += 1
else:
error += 1
return float(right)/(right+error)
evaluate(model)
Out[9]:
In [22]:
def get_result(result):
# 将 one_hot 编码解码
resultstr = ''
for i in range(n_len):
resultstr += str(np.argmax(result[i])) + ','
return resultstr
index = random.randint(0, n_test-1)
y_pred = model.predict(X_test[index].reshape(1, height, width*n_len, 1))
plt.title('real: %s\npred:%s'%(get_result([y_test[x][index] for x in range(n_len)]), get_result(y_pred)))
plt.imshow(X_test[index,:,:,0], cmap='gray')
plt.axis('off')
Out[22]:
In [23]:
model.save_weights('model.h5')
with open('model.json', 'w') as f:
f.write(model.to_json())