基于AlexNet模型的图像分类
发布时间
阅读量:
阅读量
问题描述:基于AlexNet模型的图像分类
AlexNet 框架由输入端、五个卷积端、三个全连接端以及输出端构成。其中,有三个卷积端经历了最大池化过程。
AlexNet框架的特点:采用了Relu激活函数(relu(x)=\max(x,0)),相较于sigmoid或tanh等激活函数而言,在运算速度上表现出显著优势;同时该激活函数通过分片线性结构实现非线性表达能力,并且特别适合应用于深度神经网络架构中。
局部响应归一化技术旨在优化网络性能,并且在部分卷积层中应用了归一化的处理手段
3、重叠池化:传统的池化采用无重叠的方式进行处理。各取不同区域进行特征提取。AlexNet采用了带交错的池化机制,在一定程度上能够降低模型过度拟合的风险
4、同时,AlexNet网络采用丢失输出操作减少过拟合现象。
具体实现:

inputdata.py具体描述了数据集的细节信息。其中包含了两类图像样本:一类是名为sun.jpg的图像文件,另一类则是cac.jpg类型的图像文件。系统会对这两种图像类型进行加载处理。
inputdata.py
import tensorflow as tf
import os
import numpy as np
import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()
def get_files(file_dir):
sun = []
label_sun = []
cac = []
label_cac = []
for file in os.listdir(file_dir):
name = file.split(sep='.')
if 'sun' in name[0]:
sun.append(file_dir + file)
label_sun.append(0)
else:
if 'cac' in name[0]:
cac.append(file_dir + file)
label_cac.append(1)
image_list = np.hstack((sun, cac))
label_list = np.hstack((label_sun, label_cac))
# 把标签和图片都放倒一个 temp 中 然后打乱顺序,然后取出来
temp = np.array([image_list, label_list])
temp = temp.transpose()
# 打乱顺序
np.random.shuffle(temp)
# 取出第一个元素作为 image 第二个元素作为 label
image_list = list(temp[:, 0])
label_list = list(temp[:, 1])
label_list = [int(i) for i in label_list]
return image_list, label_list
# image_W ,image_H 指定图片大小,batch_size 每批读取的个数 ,capacity队列中 最多容纳元素的个数
def get_batch(image, label, image_W, image_H, batch_size, capacity):
# 转换数据为 ts 能识别的格式
image = tf.cast(image, tf.string)
label = tf.cast(label, tf.int32)
# 将image 和 label 放倒队列里
input_queue = tf.train.slice_input_producer([image, label])
label = input_queue[1]
# 读取图片的全部信息
image_contents = tf.read_file(input_queue[0])
# 把图片解码,channels =3 为彩色图片, r,g ,b 黑白图片为 1 ,也可以理解为图片的厚度
image = tf.image.decode_png(image_contents, channels=3)
# 将图片以图片中心进行裁剪或者扩充为 指定的image_W,image_H
image = tf.image.resize_image_with_crop_or_pad(image, image_W, image_H)
# 对数据进行标准化,标准化,就是减去它的均值,除以他的方差
image = tf.image.per_image_standardization(image)
# 生成批次 num_threads 有多少个线程根据电脑配置设置 capacity 队列中 最多容纳图片的个数 tf.train.shuffle_batch 打乱顺序,
image_batch, label_batch = tf.train.batch([image, label], batch_size=batch_size, num_threads=4, capacity=capacity)
# 重新定义下 label_batch 的形状
label_batch = tf.reshape(label_batch, [batch_size])
# 转化图片
image_batch = tf.cast(image_batch, tf.float32)
return image_batch, label_batch
model.py:实现AlexNet网络框架的定义;
import tensorflow as tf
import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()
def inference(images, batch_size, n_classes):
with tf.variable_scope('conv1') as scope:
# 卷积盒的为 3*3 的卷积盒,图片厚度是3,输出是16个featuremap
weights = tf.get_variable('weights',
shape=[3, 3, 3, 16],
dtype=tf.float32,
initializer=tf.truncated_normal_initializer(stddev=0.1, dtype=tf.float32))
biases = tf.get_variable('biases',
shape=[16],
dtype=tf.float32,
initializer=tf.constant_initializer(0.1))
conv = tf.nn.conv2d(images, weights, strides=[1, 1, 1, 1], padding='SAME')
pre_activation = tf.nn.bias_add(conv, biases)
conv1 = tf.nn.relu(pre_activation, name=scope.name)
with tf.variable_scope('pooling1_lrn') as scope:
pool1 = tf.nn.max_pool(conv1, ksize=[1, 3, 3, 1], strides=[1, 2, 2, 1], padding='SAME', name='pooling1')
norm1 = tf.nn.lrn(pool1, depth_radius=4, bias=1.0, alpha=0.001 / 9.0, beta=0.75, name='norm1')
with tf.variable_scope('conv2') as scope:
weights = tf.get_variable('weights',
shape=[3, 3, 16, 16],
dtype=tf.float32,
initializer=tf.truncated_normal_initializer(stddev=0.1, dtype=tf.float32))
biases = tf.get_variable('biases',
shape=[16],
dtype=tf.float32,
initializer=tf.constant_initializer(0.1))
conv = tf.nn.conv2d(norm1, weights, strides=[1, 1, 1, 1], padding='SAME')
pre_activation = tf.nn.bias_add(conv, biases)
conv2 = tf.nn.relu(pre_activation, name='conv2')
# pool2 and norm2
with tf.variable_scope('pooling2_lrn') as scope:
norm2 = tf.nn.lrn(conv2, depth_radius=4, bias=1.0, alpha=0.001 / 9.0, beta=0.75, name='norm2')
pool2 = tf.nn.max_pool(norm2, ksize=[1, 3, 3, 1], strides=[1, 1, 1, 1], padding='SAME', name='pooling2')
with tf.variable_scope('local3') as scope:
reshape = tf.reshape(pool2, shape=[batch_size, -1])
dim = reshape.get_shape()[1].value
weights = tf.get_variable('weights',
shape=[dim, 128],
dtype=tf.float32,
initializer=tf.truncated_normal_initializer(stddev=0.005, dtype=tf.float32))
biases = tf.get_variable('biases',
shape=[128],
dtype=tf.float32,
initializer=tf.constant_initializer(0.1))
local3 = tf.nn.relu(tf.matmul(reshape, weights) + biases, name=scope.name)
# local4
with tf.variable_scope('local4') as scope:
weights = tf.get_variable('weights',
shape=[128, 128],
dtype=tf.float32,
initializer=tf.truncated_normal_initializer(stddev=0.005, dtype=tf.float32))
biases = tf.get_variable('biases',
shape=[128],
dtype=tf.float32,
initializer=tf.constant_initializer(0.1))
local4 = tf.nn.relu(tf.matmul(local3, weights) + biases, name='local4')
# softmax
with tf.variable_scope('softmax_linear') as scope:
weights = tf.get_variable('softmax_linear',
shape=[128, n_classes],
dtype=tf.float32,
initializer=tf.truncated_normal_initializer(stddev=0.005, dtype=tf.float32))
biases = tf.get_variable('biases',
shape=[n_classes],
dtype=tf.float32,
initializer=tf.constant_initializer(0.1))
softmax_linear = tf.add(tf.matmul(local4, weights), biases, name='softmax_linear')
return softmax_linear
def losses(logits, labels):
with tf.variable_scope('loss') as scope:
cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits \
(logits=logits, labels=labels, name='xentropy_per_example')
loss = tf.reduce_mean(cross_entropy, name='loss')
tf.summary.scalar(scope.name + '/loss', loss)
return loss
def trainning(loss, learning_rate):
with tf.name_scope('optimizer'):
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate)
global_step = tf.Variable(0, name='global_step', trainable=False)
train_op = optimizer.minimize(loss, global_step=global_step)
return train_op
def evaluation(logits, labels):
with tf.variable_scope('accuracy') as scope:
correct = tf.nn.in_top_k(logits, labels, 1)
correct = tf.cast(correct, tf.float16)
accuracy = tf.reduce_mean(correct)
tf.summary.scalar(scope.name + '/accuracy', accuracy)
return accuracy
在train.py文件中记录了网络模型的各项训练参数及其运行状态信息。文件内容涵盖以下几大模块:首先记录了识别图像类别数量以及图片分辨率信息;其次涵盖了一次性处理的数据样本数量;然后包含优化算法的学习速率设置以及总迭代次数;最后还记录了每次迭代过程中的监控指标数据信息
import os
import numpy as np
import tensorflow as tf
import input_data
import model
import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()
N_CLASSES = 2 # 2个输出神经元,
IMG_W = 200 # 重新定义图片的大小,图片如果过大则训练比较慢
IMG_H = 200
BATCH_SIZE = 4 # 每批数据的大小
CAPACITY = 256
MAX_STEP = 1000 # 训练的步数,
learning_rate = 0.0001 # 学习率,建议刚开始的 learning_rate <= 0.0001
def run_training():
# 数据集
train_dir = 'F:/deep learning/net/train/'
# logs_train_dir 存放训练模型的过程的数据,在tensorboard 中查看
logs_train_dir = 'F:/deep learning/net/save/model.ckpt/'
# 获取图片和标签集
train, train_label = input_data.get_files(train_dir)
# 生成批次
train_batch, train_label_batch = input_data.get_batch(train,
train_label,
IMG_W,
IMG_H,
BATCH_SIZE,
CAPACITY)
# 进入模型
train_logits = model.inference(train_batch, BATCH_SIZE, N_CLASSES)
# 获取 loss
train_loss = model.losses(train_logits, train_label_batch)
# 训练
train_op = model.trainning(train_loss, learning_rate)
# 获取准确率
train__acc = model.evaluation(train_logits, train_label_batch)
# 合并 summary
summary_op = tf.summary.merge_all()
sess = tf.Session()
# 保存summary
train_writer = tf.summary.FileWriter(logs_train_dir, sess.graph)
saver = tf.train.Saver()
sess.run(tf.global_variables_initializer())
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(sess=sess, coord=coord)
try:
for step in np.arange(MAX_STEP):
if coord.should_stop():
break
_, tra_loss, tra_acc = sess.run([train_op, train_loss, train__acc])
if step % 50 == 0:
print('Step %d, train loss = %.2f, train accuracy = %.2f%%' % (step, tra_loss, tra_acc * 100.0))
summary_str = sess.run(summary_op)
train_writer.add_summary(summary_str, step)
if step % 2000 == 0 or (step + 1) == MAX_STEP:
# 每隔2000步保存一下模型,模型保存在 checkpoint_path 中
checkpoint_path = os.path.join(logs_train_dir, 'model.ckpt')
saver.save(sess, checkpoint_path, global_step=step)
except tf.errors.OutOfRangeError:
print('Done training -- epoch limit reached')
finally:
coord.request_stop()
coord.join(threads)
sess.close()
# train
run_training()
test.py:定义了网络的测试情况
import tensorflow as tf
from PIL import Image
import matplotlib.pyplot as plt
import input_data
import numpy as np
import model
import os
import cv2
import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()
# 从指定目录中选取一张图片
def get_one_image(train):
files = os.listdir(train)
n = len(files)
ind = np.random.randint(0, n)
img_dir = os.path.join(train, files[ind])
image = Image.open(img_dir)
plt.imshow(image)
plt.show()
image = image.resize([200, 200])
image = np.array(image)
#image = cv2.add(img2, image)
# plt.imshow(image)
#plt.show()
return image
def evaluate_one_image():
train = 'F:/deep learning/net/test/sun/'
image_array = get_one_image(train)
with tf.Graph().as_default():
BATCH_SIZE = 1 # 因为只读取一副图片 所以batch 设置为1
N_CLASSES = 2 # 2个输出神经元,
# 转化图片格式
image = tf.cast(image_array, tf.float32)
# 图片标准化
image = tf.image.per_image_standardization(image)
# 图片原来是三维的 [200, 200, 3] 重新定义图片形状 改为一个4D 四维的 tensor
image = tf.reshape(image, [1, 200, 200, 3])
logit = model.inference(image, BATCH_SIZE, N_CLASSES)
# 因为 inference 的返回没有用激活函数,所以在这里对结果用softmax 激活
logit = tf.nn.softmax(logit)
# 用最原始的输入数据的方式向模型输入数据 placeholder
x = tf.placeholder(tf.float32, shape=[200, 200, 3])
# 存放模型的路径
logs_train_dir = 'F:/deep learning/net/save/model.ckpt/'
# 定义saver
saver = tf.train.Saver()
with tf.Session() as sess:
print("从指定的路径中加载模型。。。。")
# 将模型加载到sess 中
ckpt = tf.train.get_checkpoint_state(logs_train_dir)
if ckpt and ckpt.model_checkpoint_path:
global_step = ckpt.model_checkpoint_path.split('/')[-1].split('-')[-1]
saver.restore(sess, ckpt.model_checkpoint_path)
print('模型加载成功, 训练的步数为 %s' % global_step)
else:
print('模型加载失败,,,文件没有找到')
# 将图片输入到模型计算
prediction = sess.run(logit, feed_dict={x: image_array})
# 获取输出结果中最大概率的索引
max_index = np.argmax(prediction)
if max_index == 0:
print('图像预测:向日葵类图片的概率 %.6f' %prediction[:, 0])
else:
print('图像预测:仙人掌类图片的概率 %.6f' %prediction[:, 1])
# 测试
evaluate_one_image()
运行结果如下:


总结:本次实验中使用了400张左右的训练集图片数量。此外,在该网络模型的设计阶段发现其参数配置较为随意,在缺乏多轮对比实验的情况下难以准确评估性能水平。因此建议应当适当增加数据集规模并优化相关参数设置以提升分类精度。
全部评论 (0)
还没有任何评论哟~
