之前公司项目有使用CNN识别人脸,于是写写博客,复习一下~~~
手机头像的解锁功能,首先是在第一次设置头像解锁的时候,使用前置摄像头拍摄一段关于自己的小视频,再处理成N张自己的照片,将这些图片打上标签,再与其他人的照片混合在一起,就构成了图片的原始训练数据集和测试数据集。
然后使用CNN模型进行训练,在需要解锁的时候,使用前置摄像头识别头像,再进行分类,识别我与非我。我,解锁。非我,不解锁。
首先,加载我们的图片们
#打开训练图片数据
filedir = "C:\\Users\\lenovo\\Documents\\tfstudy\\pic"
categorys = ["me","notme"]
imagearrays,labels,_ = util.image_arrays(categorys, filedir, True)
imagearrays.shape
#打开测试图片数据
filedir = "C:\\Users\\lenovo\\Documents\\tfstudy\\pic\\meornotme"
testarrays,testlabels,_ = util.image_arrays(categorys, filedir, True)
testarrays.shape
这里加载的图片大小为1920 * 1080
图片的labels使用get_dummies()方法进行哑变量处理,即:
labels = pd.get_dummies(labels)
labels.columns = [1, 2]
labels
创建一个next_batch()的方法,以便后续的随机梯度下降:
#准备训练数据
def next_batch(batchsize, x, y):
n_batches = x.shape[0] // batchsize
x = x[:n_batches * batch_size, :, : , :]
y = y.iloc[:n_batches * batchsize, :]
for n in range(0, len(y), batchsize):
batch_x = x[n : n + batchsize, :, :, :]
batch_y = y.iloc[n : n + batchsize, :]
yield batch_x, batch_y
在处理完我们的训练集数据和测试集数据后,我们还可以顺便选一张图片显示一下,保证取出数据的准确性:
#展示其中一张图片
%matplotlib inline
import matplotlib.pyplot as plt
plt.imshow(np.reshape(data[11],(1920,1080)), cmap ='gray')
运行得到博主我的女友照片一张(哈哈,没人可以和我抢!!):
准备工作现在完成,开始我们CNN网络的搭建,CNN网络的搭建参考Alexnet,图片处理流程图如下:
#设置超参数
learning_rate = 0.01
epochs = 10000 #一共运行几大轮
batch_size = 256 #随机梯度下降,一小轮含多少张图片
#用来验证和计算模型评分的样本数
test_valid_size = 256
#神经网络参数
n_classess = 2 #只有两类,我和非我
drop_out = 0.75
weights = {
#卷积层1 : 11 * 11 数量48个 步长4
"wc1" : tf.Variable(tf.truncated_normal([11, 11, 1, 48], dtype=tf.float32)),
#卷积层2 : 5 * 5 数量128个 步长1
"wc2" : tf.Variable(tf.truncated_normal([5, 5, 48, 128], dtype=tf.float32)),
#卷积层3: 3 * 3 数量192个 步长1
"wc3" : tf.Variable(tf.truncated_normal([3, 3, 128, 192], dtype=tf.float32)),
#卷积层4: 3 * 3 数量192个 步长1
"wc4" : tf.Variable(tf.truncated_normal([3, 3, 192, 192], dtype=tf.float32)),
#卷积层5: 3 * 3 数量128个 步长1
"wc5" : tf.Variable(tf.truncated_normal([3, 3, 192, 128], dtype=tf.float32)),
#全连接层1: 含1024个隐藏神经元
"wd1" : tf.Variable(tf.truncated_normal([60 * 34 * 128, 1024], dtype=tf.float32)),
#全连接层2: 含1024个隐藏神经元
"wd2" : tf.Variable(tf.truncated_normal([1024, 1024], dtype=tf.float32)),
#softmax全连接层: 含两个out神经元
"out" : tf.Variable(tf.truncated_normal([1024, n_classess], dtype=tf.float32))
}
biases = {
"bc1" : tf.Variable(tf.zeros([48], dtype=tf.float32)),
"bc2" : tf.Variable(tf.zeros([128], dtype=tf.float32)),
"bc3" : tf.Variable(tf.zeros([192], dtype=tf.float32)),
"bc4" : tf.Variable(tf.zeros([192], dtype=tf.float32)),
"bc5" : tf.Variable(tf.zeros([128], dtype=tf.float32)),
"bd1" : tf.Variable(tf.zeros([1024], dtype=tf.float32)),
"bd2" : tf.Variable(tf.zeros([1024], dtype=tf.float32)),
"out" : tf.Variable(tf.zeros([n_classess], dtype=tf.float32))
}
卷积层处理:
def con2d(x, w , b, strides = 1, mode = "SAME"):
x = tf.nn.conv2d(input=x, filter=w,
strides = [1, strides, strides, 1], padding = mode)
return tf.nn.relu(x)
池化层处理:
def maxpool2d(x, k = 2, mode = "SAME"):
x = tf.nn.max_pool(x, strides=[1, k, k, 1],
ksize = [1, k, k, 1], padding = mode)
return x
CNN网络的搭建:
def conv_net(x, weights, biases, dropout = 1):
#卷积层1 1920 * 1080 to 480 * 270
conv1 = con2d(x, weights["wc1"], biases["bc1"], strides=4)
#池化 480 * 270 to 240 * 135
conv1 = maxpool2d(conv1, k = 2)
#卷积层2 240 * 135 to 240 * 135
conv2 = con2d(conv1, weights["wc2"], biases["bc2"], strides=1)
#池化 240 * 135 to 120 * 68
conv2 = maxpool2d(conv2, k = 2)
#卷积层3 120 * 68 to 120 * 68
conv3 = con2d(conv2, weights["wc3"], biases["bc3"], strides=1)
#卷积层4 120 * 68 to 120 * 68
conv4 = con2d(conv3, weights["wc4"], biases["bc4"], strides=1)
#卷积层5 120 * 68 to 120 * 68
conv5 = con2d(conv4, weights["wc5"], biases["bc5"], strides=1)
#池化 120 * 68 to 60 * 34
conv5 = maxpool2d(conv5, k = 2)
#全连接层1 60 * 34 * 128 to 1024
fc1 = tf.reshape(conv5, shape = [-1, weights["wd1"].get_shape().as_list()[0]])
fc1 = tf.matmul(fc1, weights["wd1"])
fc1 = tf.add(fc1, biases["bd1"])
fc1 = tf.nn.relu(fc1)
fc1 = tf.nn.dropout(fc1, keep_prob=dropout)
#全连接层2 1024 to 1024
fc2 = tf.matmul(fc1, weights["wd2"])
fc2 = tf.add(fc2, biases["bd2"])
fc2 = tf.nn.relu(fc2)
fc2 = tf.nn.dropout(fc1, keep_prob=dropout)
#输出层 1024 to 2
out = tf.matmul(fc2, weights["out"])
out = tf.add(out, biases["out"])
return out
构建损失,梯度下降,准确率:
#损失与梯度下降
logits = conv_net(x, weights, biases, keep_prob)
loss = tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=y)
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(loss)
#准确率
correct_pred = tf.equal(tf.argmax(logits, 1), tf.argmax(y, 1))
accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))
一切准备就绪,现在开启Session会话,运行随机梯度下降,最后检测模型的准确度:
#启动会话,开始训练
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for epoch in range(epochs):
accur = 0
for batch_x, batch_y in next_batch(batch_size, data, labels):
feed = {
x : batch_x,
y : batch_y,
keep_prob : drop_out
}
feed_valid = {
x : batch_x,
y : batch_y,
keep_prob : 1
}
sess.run(optimizer, feed_dict=feed)
valid_accur = sess.run(accuracy, feed_dict=feed_valid)
accur += valid_accur
print("第",epoch, "轮,准确率为:", accur/(data.shape[0]// batch_size))
#测试集准确率
test_acc = sess.run(accuracy, feed_dict={
x: testdata,
y: testlabels,
keep_prob :1.})
print('Testing Accuracy: {}'.format(test_acc))
源码地址:
https://github.com/freeingfree/cnn