pythontensorflow学习(四)加⼤难度!AlexNet模型实现
加⼤难度!AlexNet模型实现
Alex ⽹络[8]是现代意义上的深度卷积神经⽹络的起源,是在 2012 年被推出
的⼀个经典⽹络模型,取得了同年 ImageNet ⽐赛的最优成绩。相⽐于上⼀章的 LeNet-5,AlexNet 的层次显著加深,参数规模也显著变⼤。
⼤纲:
猫狗⼤战数据集处理
数据集的加⼯
转换为TFRecord格式
Alex⽹络模型实现
⽹络模型架构
模型的训练存储及结果可视化
猫狗⼤战数据集处理
猫狗⼤战的数据集来源于Kaggle上的⼀个竞赛:Dogs vs. Cats。该数据集包括12500张猫的图⽚以及12500张狗的图⽚,是⼀个⼆分类问题。官⽅提供了免费下载:.如果不想注册账号,还有微软的版本:。
不同于MNIIST数据集,这个数据集均来⾃于真实的照⽚,tensorflow中也没有封装好的函数来读取该数据,所以需要对该数据进⾏预处理。
数据集的加⼯
⾸先,AlexNet模型的输⼊图像⼤⼩为227×227×3,所以需要把数据集的分辨率调整为该⼤⼩,这⾥使⽤opencv进⾏处理
# 把图⽚⼤⼩转换为227x227x3
def rebuild(dir):
for root, dirs, files in os.walk(dir):
for file in files:
try:
filepath = os.path.join(root, file)
image = cv2.imread(filepath)
dim =(227,227)
resized = size(image, dim)
print(file)
path ="D:/cat_and_dog/Cat/"+file
cv2.imwrite(path, resized)
except IOError:
print(filepath)
cv2.waitKey(0) # 退出
rebuild("D:/PetImages/Cat")
对于损坏的数据,这⾥使⽤os.remove()直接删除。
转换为TFRecord格式
在第⼆章介绍过了TFRecord⽂件的创建和读取,传送门-> 这⾥不再介绍,直接贴源代码:
获取数据集和标签:
def get_file(file_dir):
images =[]
temp =[]
for root, sub_folders, files in os.walk(file_dir):
for name in files:
images.append(os.path.join(root, name))
for name in sub_folders:
temp.append(os.path.join(root, name))
labels =[]
for one_folder in temp:
n_img =len(os.listdir(one_folder))
letter = one_folder.split("\\")[-1]
if letter=='Cat':
labels = np.append(labels, n_img*[0])
else:
labels = np.append(labels, n_img*[1])
temp = np.array([images, labels])
temp = anspose()
np.random.shuffle(temp)
image_list =list(temp[:,0])
label_list =list(temp[:,1])
label_list =[int(float(i))for i in label_list]
return image_list, label_list
imagelist, labellist =get_file("D:/cat_and_dog")
转换为TFRecord⽂件:
# ⽣成TFRecord⽂件
def int64_feature(value):
ain.Feature(int64_ain.Int64List(value=value))
def bytes_feature(value):
ain.Feature(bytes_ain.BytesList(value=[value]))
def ToTFRecord(image_list, label_list, save_dir, name):
filename = os.path.join(save_dir, name+'.tfrecords')
n_samples =len(imagelist)
writer = tf.python_io.TFRecordWriter(filename)
print("")
for i in np.arange(0, n_samples):
try:
image = cv2.imread(image_list[i])
image_raw = string()
label =[int(label_list[i])]
example = tf.train.Example(ain.Features(feature={
'label':int64_feature(label),
'image_raw':bytes_feature(image_raw)
}))
writer.write(example.SerializeToString())
except IOError as e:
print('could not read:', image_list[i])
writer.close()
print('transform done!')
其中save_dir和name分别是存储路径和⽂件名。
⾄此TFRecord⽂件已经⽣成,还需要⼀个能读取该⽂件的函数来获取数据:
def read_and_decode(tfrecord_file, batch_size):
filename_queue = tf.train.string_input_producer([tfrecord_file])
reader = tf.TFRecordReader()
_, serialized_example = ad(filename_queue)
img_features = tf.parse_single_example(
serialized_example,
features={
'label': tf.FixedLenFeature([], tf.int64),
'image_raw': tf.FixedLenFeature([], tf.string),
})
image = tf.decode_raw(img_features['image_raw'], tf.uint8)
image = tf.reshape(image,[227,227,3])
label = tf.cast(img_features['label'], tf.int32)
image_batch, label_batch = tf.train.shuffle_batch([image, label],
batch_size=batch_size,
min_after_dequeue=100,
num_threads=64,
capacity=200
)
return image_batch, tf.reshape(label_batch,[batch_size])
image_batch, label_batch =read_and_decode('cat_and_dog.tfrecords',25)
该函数每次读取指定数⽬的数据集以便训练时提供。
⽹络模型架构
在实现每⼀层的架构之前,先对参数进⾏集中管理,这是⼀个很好的习惯:
# 集中管理参数
learning_rate =1e-4 # 学习速率
training_iters =200 # 迭代次数
batch_size =50 # 每批的⼤⼩
n_classes =2 # 种类
n_fc1 =4096
n_fc2 =2048
# 构建模型
x = tf.placeholder(tf.float32,[None,227,227,3])
y = tf.placeholder(tf.int32,[None, n_classes])
W_conv ={
'conv1': tf.uncated_normal([11,11,3,96], stddev=0.0001)),
'conv2': tf.uncated_normal([5,5,96,256], stddev=0.01)),
'conv3': tf.uncated_normal([3,3,256,384], stddev=0.01)),
'conv4': tf.uncated_normal([3,3,384,384], stddev=0.01)),
'conv5': tf.uncated_normal([3,3,384,256], stddev=0.01)),
'fc1': tf.uncated_normal([6*6*256, n_fc1], stddev=0.1)),
'fc2': tf.uncated_normal([n_fc1, n_fc2], stddev=0.1)),
'fc3': tf.uncated_normal([n_fc2, n_classes], stddev=0.1))
}
b_conv ={
'conv1': tf.stant(0.0, dtype=tf.float32, shape=[96])),
'conv2': tf.stant(0.1, dtype=tf.float32, shape=[256])),
'conv3': tf.stant(0.1, dtype=tf.float32, shape=[384])),
'conv4': tf.stant(0.1, dtype=tf.float32, shape=[384])),
'conv5': tf.stant(0.1, dtype=tf.float32, shape=[256])),
'fc1': tf.stant(0.1, dtype=tf.float32, shape=[n_fc1])),
'fc2': tf.stant(0.1, dtype=tf.float32, shape=[n_fc2])),
'fc3': tf.stant(0.0, dtype=tf.float32, shape=[n_classes]))
}
下⾯实现各层:
第⼀层卷积池化
# 第⼀层卷积
conv1 = bias_v2d(x, W_conv['conv1'], strides=[1,4,4,1], padding='SAME'), b_conv['conv1']))
pool1 = tf.nn.avg_pool(conv1, ksize=[1,3,3,1], strides=[1,2,2,1], padding='VALID')
# LRN局部相应归⼀化
norm1 = tf.nn.lrn(pool1,5, bias=1.0, alpha=0.001/9.0, beta=0.75)
在AlexNet中使⽤了LRN(局部相应归⼀化)来缓解过拟合,后来被BN(批归⼀化)所取代。但在这⾥尽量还原原模型。第⼆层卷积池化
# 第⼆层卷积
conv2 = bias_v2d(norm1, W_conv['conv2'], strides=[1,1,1,1], padding='SAME'), b_conv['conv2']))
pool2 = tf.nn.avg_pool(conv2, ksize=[1,3,3,1], strides=[1,2,2,1], padding='VALID')
# LRN局部相应归⼀化
norm2 = tf.nn.lrn(pool2,5, bias=1.0, alpha=0.001/9.0, beta=0.75)
第三层卷积(没有进⾏池化)
# 第三层卷积
conv3 = bias_v2d(norm2, W_conv['conv3'], strides=[1,1,1,1], padding='SAME'), b_conv['conv3']))
第四层卷积(没有池化)
# 第四层卷积
conv4 = bias_v2d(conv3, W_conv['conv4'], strides=[1,1,1,1], padding='SA
ME'), b_conv['conv4']))
第五层卷积池化
# 第五层卷积
conv5 = bias_v2d(conv4, W_conv['conv5'], strides=[1,1,1,1], padding='SAME'), b_conv['conv5']))
pool5 = tf.nn.avg_pool(conv5, ksize=[1,3,3,1], strides=[1,2,2,1], padding='VALID')
将矩阵展开成⼀维进⾏第六层全连接:
reshape = tf.reshape(pool5,[-1,6*6*256])
# 第六层全连接
fc1 = lu(tf.add(tf.matmul(reshape, W_conv['fc1']), b_conv['fc1']))
# dropout
fc1 = tf.nn.dropout(fc1,0.5)
这⾥采⽤了dropout技术来抑制⼀部分神经元,以缓解过拟合
第七层全连接
# 第七层全连接
fc2 = lu(tf.add(tf.matmul(fc1, W_conv['fc2']), b_conv['fc2']))
# dropout
fc2 = tf.nn.dropout(fc2,0.5)
分类:
# 全连接分类
fc3 = tf.add(tf.matmul(fc2, W_conv['fc3']), b_conv['fc3'])
定义损失和精度:
# 定义损失
loss = tf.reduce_softmax_cross_entropy_with_logits(logits=fc3, labels=y)) optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss)
# 模型精度
correct_num = tf.equal(tf.arg_max(fc3,1), tf.arg_max(y,1))
accuracy = tf.reduce_mean(tf.cast(correct_num, tf.float32))
⾄此,整个AlexNet模型已经搭建完成!
模型的训练存储及结果可视化
tensorflow提供了⽅法以存储模型和结构及权重,即tf.sava函数。
下⾯开始训练,并将训练后的模型保存下来:
# 训练
def train():
with tf.Session()as sess:
sess.run(init)
save_model =".//model//AlexNetModel.ckpt"
train_writer = tf.summary.FileWriter(".//log", aph)
saver = tf.train.Saver()
losslist =[] # 存储损失
coord = tf.train.Coordinator()
treades = tf.train.start_queue_runners(coord=coord)
step =0
for i in range(500):
step = i
image, label = sess.run([image_batch, label_batch])
labels =onehot(label)
sess.run(optimizer, feed_dict={x: image, y: labels})
loss_record = sess.run(loss, feed_dict={x: image, y: labels})
print(loss_record)
losslist.append(loss_record)
saver = tf.train.Saver()
saver.save(sess, save_model)
print("model save finished!")
coord.join(treades)
plt.plot(losslist)
plt.xlabel('iter')
plt.ylabel('loss')
plt.tight_layout()
plt.savefig('cnn-tf-AlexNet.png', dpi=200)
上述函数⽤到了onehot函数来把标签转换为onehot形式,该函数的代码如下:
# 转换为one-hot
def onehot(label):resized
onehot_label = np.zeros([len(label),max(label)+1])
for i in range(len(label)):
onehot_label[i][label[i]]=1
return onehot_label
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论