基本的卷积神经网络包含卷积层、池化层、全连接层组成。卷积神经网络比较详细的介绍参见博客:CNN笔记:通俗理解卷积神经网络、卷积神经网络超详细介绍、卷积神经网络概述。
卷积网络的好处主要是可以减少参数数量从而降低网络的计算量,同时有助于与防止过拟合,它还可以让网络的鲁棒性更高。
使用tensorflow搭建一个双层的卷积神经网络,网络结构为: Conv2d卷积->RELU激活->Maxpool池化->Conv2d卷积->RELU激活->Maxpool池化->FLATTEN扁平化->全连接层。部分代码如下所示。
1.创建占位符
def create_placeholders(n_H0, n_W0, n_C0, n_y):
"""
参数:
n_H0 -- 图像矩阵的高
n_W0 -- 图像矩阵的宽
n_C0 -- 图像矩阵的深度
n_y -- 标签类别数量
"""
# 下面使用None来表示样本数量,表示当前还不确定样本数量
X = tf.placeholder(tf.float32, [None, n_H0, n_W0, n_C0])
Y = tf.placeholder(tf.float32, [None, n_y])
return X, Y
2.初始化参数
def initialize_parameters():
tf.set_random_seed(1)
#使用`tf.contrib.layers.xavier_initializer(seed = 0)`来初始化W1。
W1 = tf.get_variable("W1", [4, 4, 3, 8], initializer=tf.contrib.layers.xavier_initializer(seed=0))
#初始化W2
W2 = tf.get_variable("W2", [2, 2, 8, 16], initializer=tf.contrib.layers.xavier_initializer(seed=0))
parameters = {"W1": W1,
"W2": W2}
return parameters
3.前向传播
def forward_propagation(X, parameters):
"""
实现前向传播流程
输入参数:
X -- 输入特征的占位符
parameters -- 之前初始化好的"W1", "W2"参数
返回参数:
Z3 -- 最后一个全连接层的输出
"""
W1 = parameters['W1']
W2 = parameters['W2']
Z1 = tf.nn.conv2d(X, W1, strides=[1, 1, 1, 1], padding='SAME')
A1 = tf.nn.relu(Z1)
P1 = tf.nn.max_pool(A1, ksize = [1, 8, 8, 1], strides = [1, 8, 8, 1], padding='SAME')
Z2 = tf.nn.conv2d(P1, W2, strides=[1, 1, 1, 1], padding='SAME')
A2 = tf.nn.relu(Z2)
P2 = tf.nn.max_pool(A2, ksize = [1, 4, 4, 1], strides = [1, 4, 4, 1], padding='SAME')
P = tf.contrib.layers.flatten(P2)
# 指定该全连接层有6个神经元。
# activation_fn=None表示该层没有激活函数,因为后面接一个softmax层
Z3 = tf.contrib.layers.fully_connected(P, 6, activation_fn=None)
return Z3
4.计算损失函数
def compute_cost(Z3, Y):
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=Z3, labels=Y))
return cost
5.构建网络模型
def model(X_train, Y_train, X_test, Y_test, learning_rate=0.009,
num_epochs=100, minibatch_size=64, print_cost=True):
"""
参数:
X_train -- 训练集数据
Y_train -- 训练集标签
X_test -- 测试集数据
Y_test -- 测试集标签
返回值:
train_accuracy -- 训练集上的预测精准度
test_accuracy -- 测试集上的预测精准度
parameters -- 训练好的参数
"""
ops.reset_default_graph() # 重置一下tf框架
tf.set_random_seed(1)
seed = 3
(m, n_H0, n_W0, n_C0) = X_train.shape
n_y = Y_train.shape[1] # n_y是标签的类别数量,这里是6
costs = []
X, Y = create_placeholders(n_H0, n_W0, n_C0, n_y)
parameters = initialize_parameters()
Z3 = forward_propagation(X, parameters)
cost = compute_cost(Z3, Y)
# 使用adam来作为优化算法
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost)
init = tf.global_variables_initializer()
with tf.Session() as sess:
sess.run(init)
for epoch in range(num_epochs):
minibatch_cost = 0.
num_minibatches = int(m / minibatch_size)
seed = seed + 1
minibatches = random_mini_batches(X_train, Y_train, minibatch_size, seed)
for minibatch in minibatches:
(minibatch_X, minibatch_Y) = minibatch
# 执行session。训练正式开始。每一次训练一个子训练集minibatch
_ , temp_cost = sess.run([optimizer, cost], feed_dict={X:minibatch_X, Y:minibatch_Y})
minibatch_cost += temp_cost / num_minibatches
if print_cost == True and epoch % 5 == 0:
print ("Cost after epoch %i: %f" % (epoch, minibatch_cost))
if print_cost == True and epoch % 1 == 0:
costs.append(minibatch_cost)
plt.plot(np.squeeze(costs))
plt.ylabel('cost')
plt.xlabel('iterations (per tens)')
plt.title("Learning rate =" + str(learning_rate))
plt.show()
# 计算预测精准度
predict_op = tf.argmax(Z3, 1)
correct_prediction = tf.equal(predict_op, tf.argmax(Y, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
print(accuracy)
train_accuracy = accuracy.eval({X: X_train, Y: Y_train})
test_accuracy = accuracy.eval({X: X_test, Y: Y_test})
print("训练集预测精准度:", train_accuracy)
print("测试集预测精准度:", test_accuracy)
return train_accuracy, test_accuracy, parameters