猫狗大战
- 顾名思义,就是实现猫和狗的分类问题
- 数据集图像是大小不一的
- 数据集图像是彩色的
实现思路
- 处理数据集时,要对图像的大小进行统一缩放
- 将图片读取为像素矩阵,并转为卷积神经网络可以识别的形状
- 构建卷积神经网络,有卷积,有池化,有全连接
- 构建代价函数
- 构建优化器
- 迭代求出预测准确率
数据集
形如上述所示,共计25000张图片,这里做示范选取猫狗各500张。
代码实现
import tensorflow as tf
import numpy as np
import os
import cv2
import random
# 设置随机种子。(5分)
tf.set_random_seed(1)
# 猫狗数据文件夹路径
data_dir = r'data'
# 调用该方法,获取文件夹中猫狗的像素矩阵为数据,并为每条数据添加标签
def load_data(data_dir):
# 存放所有图片像素矩阵数据
data_all = []
# 存放其对应的标签
labels_all = []
# i 为每个图片数据的名字
for i in os.listdir(data_dir):
# 拼接路径 保证cv2读取正确
img = cv2.imread(os.path.join(data_dir, i))
# 将读取到的大小不一的图像进行统一缩放
img = cv2.resize(img, dsize=(128, 128))
# 转为数字矩阵
img_array = np.asarray(img)
img_array = np.reshape(img_array, (3, 128, 128))
# 直接对数据进行归一化
img_array = img_array / 127.5 - 1
# 将这个数据存放进列表
data_all.append(img_array)
# 因为图片的名字为'cat.1.jpg'等类型,所以对名字进行切割,选择第一部分,既是其对应的类型
label = i.split('.')[0]
# 将对应的类型,转为0,1,作0,1分类
if label == 'cat':
labels_all.append(1)
else:
labels_all.append(0)
# 将列表作为转为数组
data_all = np.asarray(data_all)
labels_all = np.asarray(labels_all)
labels_all = np.vstack(labels_all)
return data_all, labels_all
# 调用该方法,对数据进行洗牌
def shuffle(data, labels):
m = len(data)
o = np.random.permutation(m)
data = data[o]
labels = labels[o]
return data, labels
# 调用该方法对数据进行切分
def data_split(data, labels):
m = len(data)
l = int(m * 0.9)
x_train, x_test = data[0:l], data[l:]
y_train, y_test = labels[0:l], labels[l:]
return x_train, x_test, y_train, y_test
# 调用load_data处理数据
data_all, labels_all = load_data(data_dir)
# 调用洗牌函数对数据进行打乱
data_all, labels_all = shuffle(data_all, labels_all)
# 调用数据切分方法,对数据进行切分
x_train, x_test, y_train, y_test = data_split(data_all, labels_all)
# 设置网络的参数,学习率设置为0.0001,训练周期设为100,batch_szie设为100
learning_rate = 0.0001
n_times = 100
batch_size = 100
# 定义网络占位符
X = tf.placeholder(tf.float32, [None, 3, 128, 128])
X_img = tf.transpose(X, perm=[0, 2, 3, 1])
Y = tf.placeholder(tf.float32, [None, 1])
keep_prob = tf.placeholder(tf.float32)
# 定义神经网络结构模型
# 首先构建卷积层,用于特征提取,示例如下,可以调整卷积参数及层数,这里选择两层,激活函数选择relu
conv1 = tf.layers.conv2d(X_img, 32, (3, 3), strides=(1, 1), padding='same', activation=tf.nn.relu)
# 加入batch_normalization防止卷积层过拟合
conv1 = tf.layers.batch_normalization(conv1,momentum=0.9)
pool1 = tf.layers.max_pooling2d(conv1, (2, 2), (2, 2), padding='same')
conv2 = tf.layers.conv2d(pool1, 64, (3, 3), (1, 1), padding='same', activation=tf.nn.relu)
conv2 = tf.layers.batch_normalization(conv2,momentum=0.9)
pool2 = tf.layers.max_pooling2d(conv2, (2, 2), (2, 2), padding='same')
# 将卷积数据展平,用于构建全连接层,用于分类
flatten = tf.layers.flatten(pool2)
fc1 = tf.layers.dense(flatten, 128, activation=tf.nn.relu)
# 全连接层可以加入dropout函数用于切断一些神经元的联系,防止过拟合
fc1 = tf.nn.dropout(fc1, keep_prob=keep_prob)
# 二分类问题,最终归于一个输出即可,激活函数选择sigmoid
fc2 = tf.layers.dense(fc1, 1, activation=tf.nn.sigmoid)
# 编写定义损失函数,网络优化器采用Adam
loss = - tf.reduce_mean(Y * tf.log(fc2) + (1 - Y) * tf.log(1 - fc2))
train_op = tf.train.AdamOptimizer(learning_rate).minimize(loss)
# 预测
predict = tf.cast(fc2 > 0.5, dtype=tf.float32)
# 准确率
accuracy = tf.reduce_mean(tf.cast(tf.equal(predict, Y), dtype=tf.float32))
# 开启会话
with tf.Session() as sess:
# 创建会话并初始化全局变量
sess.run(tf.global_variables_initializer())
# 大循环训练100次
for n in range(n_times):
# 起始位置
start = 0
# 结束位置
end_ = batch_size
# acc_all存放准确率
acc_all = []
# 每次分批次循环训练
for j in range(len(x_train) // batch_size):
# 获取数据
# 执行一个逻辑判断,如果下标越界,则重置起始与结束位置
if start >= len(x_train):
start = 0
end_ = batch_size
# 分批次获取训练数据中的数据
data_batch, labels_batch = x_train[start:end_], y_train[start:end_]
# 执行训练
los, _, acc = sess.run([loss,train_op,accuracy], feed_dict={X: data_batch, Y: labels_batch, keep_prob: 0.9})
acc_all.append(acc)
accs = sess.run(accuracy, feed_dict={X: x_test, Y: y_test, keep_prob: 1})
# 每个大批次训练完毕,打印训练集平均准确率和测试集准确率
print('大批次', n + 1)
print('训练集准确率:', np.mean(acc_all))
print('测试集的准确率:', accs)
# 测试集中随机抽一个样本并进行测试,输出结果
r = random.randint(0, len(x_test) - 1)
print('随机标签', y_test[r])
print('预测标签', sess.run(predict, feed_dict={X: x_test[r], keep_prob: 1}))
效果总结
项目整体框架可以跑通,由于训练图片较少,大概10次大循环训练集就产生了过拟合,但是测试集准确率徘徊在百分之65,难有提升,这时可以加大数据量,训练一个好的模型。
版权声明:本文为qq872890060原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。