华为云深度学习kaggle猫狗识别

举报
砖头2333 发表于 2018/10/10 17:27:42 2018/10/10
【摘要】 使用华为云深度学习服务完成kaggle猫狗识别竞赛参考:1. kaggle猫狗竞赛kernel第一名的代码2. Tensorflow官网代码3. 华为云DLS服务github代码1. 环境配置与数据集处理* 首先我们需要从kaggle上面找到猫狗竞赛的页面,下载数据集压缩文件all.zip,大概853MB,解压两次后可以得到两个文件夹test和train,以及一个sample_submiss...

使用华为云深度学习服务完成kaggle猫狗识别竞赛

参考:

1. kaggle猫狗竞赛kernel第一名的代码

2. Tensorflow官网代码

3. 华为云DLS服务github代码


1. 环境配置与数据集处理


* 首先我们需要从kaggle上面找到猫狗竞赛的页面下载数据集压缩文件all.zip大概853MB解压两次后可以得到两个文件夹test和train以及一个sample_submission.csv文件test里面有12500张没有标签的测试图片train中有带标签的25000张图片猫狗各12500张且按照顺序排好了。

* 在桶的目录下创建code、log、model、train、test五个文件夹。

* 使用华为云OBS客户端上传之前解压的图片我是将解压后的图片上传的所以需要一定的时间文件位置为桶的目录下创建的train和test文件夹。

* 创建开发环境添加jupyter notebook

2. 代码-库的导入

from __future__ import division, absolute_import, print_function
import os, cv2, random
import pandas as pd
import tensorflow as tf
import numpy as np
import moxing as mox
from tensorflow import keras
from tensorflow.python.keras import layers

我使用tensorflow作为框架实现的以及最后使用pandas保存结果moxing用于读取文件cv2用于图片resize。


3. 代码-定义常量以及运行时参数

# 使用tf.app.flags定义参数运行时可以指定
tf.app.flags.DEFINE_string('data_url', 's3://dls-dogcat/input/', 'Dataset')
tf.app.flags.DEFINE_string('train_url', 's3://dls-dogcat/model/', 'Model_dir')
tf.app.flags.DEFINE_string('log_url', 's3://dls-dogcat/log/', 'Log_dir')

flags = tf.app.flags.FLAGS
TRAIN_DIR = os.path.join(flags.data_url, 'train/')
TEST_DIR = os.path.join(flags.data_url, 'test/')
MODEL_DIR = flags.train_url
LOG_DIR = flags.log_url

# 注释掉的部分用于测试
# TRAIN_DIR = 's3://dls-dogcat/input/train/'
# TEST_DIR = 's3://dls-dogcat/input/test/'
# MODEL_DIR = 's3://dls-dogcat/model/'
# LOG_DIR = 's3://dls-dogcat/log/'

# 这里获取文件夹下所有文件名称使用mox的函数或者使用tf.gfile不能使用os测试数据需要按照名称顺序排列
# 我在ubuntu下测试时发现文件名的排列规则是按照字符顺序所以这里使用循环可以避免这个问题
train_image_url = [TRAIN_DIR + i for i in mox.file.list_directory(TRAIN_DIR)]
test_image_url = []
for i in range(1, 12501):
path = TEST_DIR + str(i) + '.jpg'
test_image_url.append(path)
print('Train images : {}, Test images : {}'.format(len(train_image_url), len(test_image_url)))



# 图片压缩为64*64大小彩色3或灰度图片1
IMAGE_SIZE = 64
CHANNELS = 3

# batch大小16epoch为30但是一般不会跑完30轮因为后面我设置了earlystop
BATCH_SIZE = 16
EPOCH = 30

# STEPS_PER_EPOCH后面实际没有使用打乱训练集顺序
STEPS_PER_EPOCH = len(train_image_url) // BATCH_SIZE
random.shuffle(train_image_url)

# batch大小epoch大小为后面准备
BATCH_SIZE = 50
EPOCH = 10

# 使用mox获取文件夹下所有文件名
train_images = [TRAIN_DIR + i for i in mox.file.list_directory(TRAIN_DIR)]
test_images = [TEST_DIR + i for i in mox.file.list_directory(TEST_DIR)]

STEPS_PER_EPOCH = len(train_images) // BATCH_SIZE

# 数据集打乱
random.shuffle(train_images)

# 定义读取图片的函数并且resize大小设置为灰度图片或彩色与上面CHANNELS对应即可
def read_image(file_path):
img = cv2.imdecode(np.fromstring(mox.file.read(file_path, binary=True), np.uint8), cv2.IMREAD_COLOR)
return cv2.resize(img, (IMAGE_SIZE, IMAGE_SIZE), interpolation=cv2.INTER_CUBIC)

# 将图片数据存入array中同时除以255进行归一化
def prep_data(images):
count = len(images)
data = np.ndarray((count, IMAGE_SIZE, IMAGE_SIZE, CHANNELS), dtype=np.float32)
for i, image_file in enumerate(images):
image = read_image(image_file)
data[i] = image / 255.0
if i%1000 == 0: print('Processed {} of {}'.format(i, count))
return data

train_set = prep_data(train_image_url)
test_set = prep_data(test_image_url)
print('Train_set shape: {}, Test_set shape: {}'.format(train_set.shape, test_set.shape))

# 获取训练集对应的label就是将文件路径切分找出是否包含dog或者cat若是dog则写入1否则0
train_labels = np.ndarray((len(train_image_url), 1), np.int32)
for i, url in enumerate(train_image_url):
tag = url.split('.')[-3].split('/')[-1]
if tag == 'dog':
train_labels[i] = 1
elif tag == 'cat':
train_labels[i] = 0
print('Train_labels shape: {}'.format(train_labels.shape))

4. 代码-CNN构建

# 添加一些参数便于调整神经网络包括unitsksizestrides
f1, f2, f3, f4 = 32, 64, 128, 256
k1, k2, k3, k4 = 5, 5, 5, 5
s1, s2, s3, s4 = 2, 2, 2, 2
c1, c2, c3, c4 = 2, 2, 2, 2
fc1, fc2, fc3, fc4 = 512, 256, 128, 128

# 有三层卷积层+最大池化+Dropout然后Flatten层再是全连接层再是输出层
# 前面三层使用relu激活drop概率0.5全连接层drop概率0.5最后输出层使用sigmoid激活
# 损失函数binary_crossentropy优化器rmsprop
# 可优化部分
# 1.增大内存受限于内存总参数在大概600000以上时32GB内存会不够用增加内存可以提升CNN的复杂度也可以使用128大小的图片
# 2.使用model_to_estimator将model转为estimator然后使用GPU训练可以提升训练速度
# 3.使用vgg16取代前三层卷积层可以实现更好的效果。

def cnn_model():
model = keras.Sequential([
layers.Conv2D(f1, k1, c1, padding='SAME', activation=tf.nn.relu, input_shape=(IMAGE_SIZE, IMAGE_SIZE, CHANNELS)),
layers.MaxPool2D(strides=s1, padding='SAME'),
layers.Dropout(0.5),
layers.Conv2D(f2, k2, c2, padding='SAME', activation=tf.nn.relu),
layers.MaxPool2D(strides=s2, padding='SAME'),
layers.Dropout(0.5),
layers.Conv2D(f3, k3, c3, padding='SAME', activation=tf.nn.relu),
layers.MaxPool2D(strides=s3, padding='SAME'),
layers.Dropout(0.5),
#         layers.Conv2D(f4, k4, c4, padding='SAME', activation=tf.nn.relu),
#         layers.MaxPool2D(strides=s4, padding='SAME'),
#         layers.Dropout(0.5),
layers.Flatten(),
layers.Dense(fc1, activation=tf.nn.relu),
layers.Dropout(0.5),
layers.Dense(fc2, activation=tf.nn.relu),
layers.Dropout(0.5),
#         layers.Dense(fc3, activation=tf.nn.relu),
#         layers.Dropout(0.5),
#         layers.Dense(fc4, activation=tf.nn.relu),
#         layers.Dropout(0.5),
layers.Dense(1, activation=tf.nn.sigmoid)
])
model.compile(loss='binary_crossentropy',
optimizer=tf.keras.optimizers.RMSprop(lr=1e-4),
metrics=['accuracy'])
return model

model = cnn_model()
model.summary()

图像处理使用卷积为了避免过拟合使用了dropout最后输出层为一个unit因为是二分类激活函数使用sigmoid

所以使用binary_crossentropy为损失函数。

5. 代码-训练模型

# 设置PrintLoss callback在训练过程中打印损失和准确率
# 设置early_stop避免过拟合
# 设置tensorboard callback记录训练过程中loss、acc、val_loss、val_acc
# 设置checkpoint_callback保存训练过程中的模型
# 由于cp_callback、tb_callback不能直接写入所以在华为云上实际运行时没有使用如果跑在自己的机器上可以使用
early_stop = tf.keras.callbacks.EarlyStopping(monitor='val_loss',
patience=3,
mode='auto')

checkpoint_path = MODEL_DIR + "cp-{epoch:04d}.ckpt"
cp_callback = tf.keras.callbacks.ModelCheckpoint(checkpoint_path,
verbose=1,
save_weights_only=True,
period=5)

tb_callback = tf.keras.callbacks.TensorBoard(log_dir=LOG_DIR, batch_size=BATCH_SIZE)

class PrintLoss(keras.callbacks.Callback):
def on_epoch_end(self, epoch, logs):
print('Epoch: {:03d} - loss: {:.5f} - acc: {:.5f} - val_loss: {:.5f} - val_acc: {:.5f}'.format(epoch + 1,
logs['loss'],
logs['acc'],
logs['val_loss'],
logs['val_acc']))

# 设置validation_split获取验证集损失
history = model.fit(train_set,
train_labels,
epochs=EPOCH,
batch_size=BATCH_SIZE,
validation_split=0.2,
verbose=0,
callbacks=[early_stop, cp_callback, tb_callback, PrintLoss()])

# 随便测试一下模型对训练集前3000图片的准确率
model.evaluate(train_set[:3000], train_labels[:3000])

6. 代码-预测与写入

# 调用predict进行预测
predictions = model.predict(test_set)

import pandas as pd
# path = os.path.join(flags.log_dir, 'submission.csv')
path = 's3://dls-dogcat/log/submission.csv'
counter = range(1, len(predictions) + 1)
df = pd.DataFrame({'id': counter, 'label': predictions})
# df['label'] = df['label'].map(lambda x: x.lstrip('[').rstrip(']')).astype('float32')
# df.reindex(index=list(range(1, df.shape[0])))
result = df.to_csv(path_or_buf=None, index=None)
with tf.gfile.Open(path, 'w') as f:
f.write(result)
print('write success')

submission格式有要求columns为id和labellabel列下的数据格式要对以及向桶中写数据的方式参考华为云项目在github中的代码。

7. kaggle分数

keras.png



【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。