使用华为云深度学习服务完成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大小16,epoch为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)# 使用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.0if i%1000 == 0: print('Processed {} of {}'.format(i, count))return datatrain_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] = 1elif tag == 'cat':train_labels[i] = 0print('Train_labels shape: {}'.format(train_labels.shape))

4. 代码-CNN构建

# 添加一些参数,便于调整神经网络,包括units,ksize,strides
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 modelmodel = 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和label,label列下的数据格式要对,以及向桶中写数据的方式,参考华为云项目在github中的代码

7. kaggle分数

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

进阶版主要使用了moxing和tensorflow框架,好处在于可以直接使用华为云GPU,非常迅速即可调试,坏处在于需要对自己的代码进行修改以适配框架

1. 数据处理

将图片数据存储为tfrecord,我对图片进行了resize处理,可以产生image size 128和64两种tfrecord,同时划分了train、eval数据集

代码参考华为云dls-example的使用moxing玩冰山

# 前面的部分代码和keras模式基本相同,将图片数据处理为numpy数组,不同的地方在于这个numpy数组我reshape为二维的了
# coding=utf-8
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
import matplotlib.pyplot as plt
import moxing.tensorflow as mtf
from sklearn.model_selection import train_test_split
from tensorflow import keras
from tensorflow.python.keras import layers
slim = tf.contrib.slimprint('load lib success', tf.VERSION)TRAIN_DIR = 's3://dls-dogcat/input/train/'
TEST_DIR = 's3://dls-dogcat/input/test/'
OUTPUT_DIR = 's3://dls-dogcat/input/128'
TRAIN64 = 'train64.tfrecord'
EVAL64 = 'eval64.tfrecord'
TEST64 = 'test64.tfrecord'TRAIN128 = 'train128.tfrecord'
EVAL128 = 'eval128.tfrecord'
TEST128 = 'test128.tfrecord'train_image_url = [TRAIN_DIR + i for i in mox.file.list_directory(TRAIN_DIR)]IMAGE_SIZE = 64
CHANNELS = 3random.shuffle(train_image_url)TRAIN_SIZE = len(train_image_url)
TEST_SIZE = len(tf.gfile.ListDirectory(TEST_DIR))
test_image_url = []
for i in range(1, TEST_SIZE + 1):path = TEST_DIR + str(i) + '.jpg'test_image_url.append(path)
print('Train images : {}, Test images : {}'.format(TRAIN_SIZE, TEST_SIZE))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)def prep_data(images):count = len(images)data = np.ndarray((count, IMAGE_SIZE * IMAGE_SIZE * CHANNELS), dtype=np.float32) # data也要改变对应下面for i, image_file in enumerate(images):image = read_image(image_file)image = image.reshape(-1) # 为了使用tfrecord的floatlist,我reshape了一下,其实可以使用byteslist,就不用reshapedata[i] = image / 255.0if i%1000 == 0: print('Processed {} of {}'.format(i, count))return datatrain_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))train_labels = np.ndarray((len(train_image_url), 1), np.int64)
for i, url in enumerate(train_image_url):tag = url.split('.')[-3].split('/')[-1]if tag == 'dog':train_labels[i] = 1elif tag == 'cat':train_labels[i] = 0
# 在这里划分数据集,80%train, 20%eval
print('Train_labels shape: {}'.format(train_labels.shape))
train_imgs, eval_imgs, train_labels, eval_labels = train_test_split(train_set, train_labels, test_size=0.2)
print(train_imgs.shape, eval_imgs.shape, train_labels.shape, eval_labels.shape)# 将train和eval的numpy数组写入tfrecord的函数,这里需要定义Features,一个是image保存图片数组,一个是label保存标签(1、0)
# FloatList要求数组为一维的,所以上面我reshape了,如果使用byteslist就不用
def convert_and_encode_to_tfrecord(num_samples, images, labels, output_file):output_file = os.path.join(OUTPUT_DIR, output_file)with tf.python_io.TFRecordWriter(output_file) as tfrecord_writer:for i in range(num_samples):example = tf.train.Example(features=tf.train.Features(feature={'image': tf.train.Feature(float_list=tf.train.FloatList(value=images[i])),'label': tf.train.Feature(int64_list=tf.train.Int64List(value=labels[i]))}))tfrecord_writer.write(example.SerializeToString())
# 此处执行完毕会产生train64.tfrecord和eval64.tfrecord两个文件,train0.916GB,eval234MB,tfrecord比源文件大是很正常的
convert_and_encode_to_tfrecord(train_imgs.shape[0], train_imgs, train_labels, TRAIN64)
convert_and_encode_to_tfrecord(eval_imgs.shape[0], eval_imgs, eval_labels, EVAL64)# 同理,这里将test写入tfrecord,但是test没有label,所以只需要一个feature
def convert_test_and_encode_to_tfrecord(num_samples, images, output_file):output_file = os.path.join(OUTPUT_DIR, output_file)with tf.python_io.TFRecordWriter(output_file) as tfrecord_writer:for i in range(num_samples):example = tf.train.Example(features=tf.train.Features(feature={'image': tf.train.Feature(float_list=tf.train.FloatList(value=images[i]))}))tfrecord_writer.write(example.SerializeToString())
# 大概586MB
convert_test_and_encode_to_tfrecord(test_set.shape[0], test_set, TEST64)# 读取tfrecord的数据并显示出来,就可以验证是否正确的存入了数据,使用mox的get_tfrecord,参数照着改就完事了
# 这个方法不能与下面读取test一起使用,因为使用了session
def read_and_decode_tfrecord(dataset_dir, file_pattern, num_samples):keys_to_features = {'image': tf.FixedLenFeature((IMAGE_SIZE * IMAGE_SIZE * CHANNELS,), tf.float32, default_value=None),'label': tf.FixedLenFeature([1], tf.int64, default_value=None),}# 这里可以实现对一维数组的reshape,我们将数据恢复为彩色图片的三维形式items_to_handlers = {'image': slim.tfexample_decoder.Tensor('image', shape=[IMAGE_SIZE, IMAGE_SIZE, CHANNELS]),'label': slim.tfexample_decoder.Tensor('label', shape=[]),}dataset = mtf.get_tfrecord(dataset_dir=dataset_dir,file_pattern=file_pattern,num_samples=num_samples,keys_to_features=keys_to_features,items_to_handlers=items_to_handlers,shuffle=False,num_epochs=1)image, label = dataset.get(['image', 'label'])sv = tf.train.Supervisor()# 这里可以显示图片,20张彩色图片with sv.managed_session() as sess:plt.figure()for i in range(20):subp = plt.subplot(4, 5, i + 1)plt.subplots_adjust(hspace=1)subp.imshow(sess.run(image))label_eval = sess.run(label)subp.set_title('label=%s' % (label_eval))plt.show()read_and_decode_tfrecord(dataset_dir=OUTPUT_DIR,file_pattern='eval*.tfrecord',num_samples=5000)def read_test_and_decode_tfrecord(dataset_dir, file_pattern, num_samples):keys_to_features = {'image': tf.FixedLenFeature((IMAGE_SIZE * IMAGE_SIZE * CHANNELS,), tf.float32, default_value=None)}items_to_handlers = {'image': slim.tfexample_decoder.Tensor('image', shape=[IMAGE_SIZE, IMAGE_SIZE, CHANNELS])}dataset = mtf.get_tfrecord(dataset_dir=dataset_dir,file_pattern=file_pattern,num_samples=num_samples,keys_to_features=keys_to_features,items_to_handlers=items_to_handlers,shuffle=False,num_epochs=1)image = dataset.get(['image'])sv = tf.train.Supervisor()with sv.managed_session() as sess:plt.figure()for i in range(20):subp = plt.subplot(4, 5, i + 1)plt.subplots_adjust(hspace=1)subp.imshow(sess.run(image[0])) # 注意这个位置,test读出来的形式不一样,需要取image[0]才是正确的图片信息,此处有伏笔plt.show()read_test_and_decode_tfrecord(dataset_dir=OUTPUT_DIR,file_pattern='test*.tfrecord',num_samples=12500)

2. 代码

经过上面的数据处理会得到三个tfrecord,分别是train、eval、test,可以修改参数得到128大小的tfrecord,文件大小为train3.66GB,eval0.915GB,test2.28GB

# 前面部分不必多说,是一些固定的库以及参数
from __future__ import absolute_import, division, print_function
import os
os.environ.pop('http_proxy', None)
import math
import numpy as np
import pandas as pd
import tensorflow as tf
import moxing.tensorflow as mox
from tensorflow.python.keras import layersslim = tf.contrib.slim NUM_SAMPLES_TRAIN = 20000
NUM_SAMPLES_EVAL = 5000
NUM_SAMPLES_TEST = 12500
# image_size对应之前存入tfrecord的图片大小
IMAGE_SIZE = 128
CHANNELS = 3# 定义flags参数,这些参数将在创建作业时指定,有batch_size,data_url数据集路径,log_url日志以及checkpoint的路径、csv文件存储路径,is_training决定训练还是预测
tf.flags.DEFINE_integer('batch_size', 16, 'Mini-batch size')
tf.flags.DEFINE_string('data_url', 's3://zxy/model/zzy', 'Dir of dataset')
tf.flags.DEFINE_string('log_dir', 's3://zxy/model/zzy/log', 'Dir of log')
tf.flags.DEFINE_boolean('is_training', True, 'True for train. False for eval and predict.')
flags = tf.flags.FLAGS # 这个地方加上去可以避免因为obs传数据不稳定造成的失败,本质上是将桶内的数据拷贝到cache中
import atexit
import logging
_data_url = flags.data_url
_log_dir = flags.log_dir
if not mox.file.is_directory(_log_dir):mox.file.make_dirs(_log_dir)
mox.file.make_dirs('/cache/data_url')
mox.file.make_dirs('/cache/log_dir')
mox.file.copy_parallel(_data_url, '/cache/data_url')
mox.file.copy_parallel(_log_dir, '/cache/log_dir')
flags.data_url = '/cache/data_url'
flags.log_dir = '/cache/log_dir'
atexit.register(lambda: mox.file.copy_parallel('/cache/log_dir', _log_dir))
logger = logging.getLogger()
while logger.handlers:logger.handlers.pop()# 这个部分实现了查询当前环境下的GPU数量,并据此定义steps,后面要用
num_gpus = mox.get_flag('num_gpus')
# if using distributed, the number of workers is related to the number of machines.
num_workers = len(mox.get_flag('worker_hosts').split(','))
steps_per_epoch = int(math.ceil(float(NUM_SAMPLES_TRAIN) / (flags.batch_size * num_gpus * num_workers)))
submission = pd.DataFrame(columns=['label']) # 定义输入函数,返回image、label,使用方式类似上面显示tfrecord的图片
def input_fn(run_mode, **kwargs): # Trainif run_mode == mox.ModeKeys.TRAIN: num_samples = NUM_SAMPLES_TRAIN num_epochs = None shuffle = True file_pattern = 'train*.tfrecord' # Eval or Testelse: num_epochs = 1 shuffle = False if run_mode == mox.ModeKeys.EVAL: num_samples = NUM_SAMPLES_EVAL file_pattern = 'eval*.tfrecord' else: num_samples = NUM_SAMPLES_TEST file_pattern = 'test*.tfrecord' keys_to_features = { 'image': tf.FixedLenFeature((IMAGE_SIZE * IMAGE_SIZE * CHANNELS,), tf.float32, default_value=None)} items_to_handlers = { 'image': slim.tfexample_decoder.Tensor('image', shape=[IMAGE_SIZE, IMAGE_SIZE, CHANNELS])} if run_mode != mox.ModeKeys.PREDICT: keys_to_features['label'] = tf.FixedLenFeature([1], tf.int64, default_value=None) items_to_handlers['label'] = slim.tfexample_decoder.Tensor('label', shape=[]) # returns an instance of 'DatasetDataProvider' # defined in 'tensorflow/contrib/slim/python/data/dataset_data_provider.py'dataset = mox.get_tfrecord(dataset_dir=flags.data_url, file_pattern=file_pattern, num_samples=num_samples, keys_to_features=keys_to_features, items_to_handlers=items_to_handlers, num_epochs=num_epochs, shuffle=shuffle) # 如果运行的是predict,返回image,如果是train或eval,返回image和labelif run_mode == mox.ModeKeys.PREDICT: image = dataset.get(['image']) # Non-DMA safe string cannot tensor may not be copied to a GPU. # So we encode string to a list of integer. return imageelse: image, label = dataset.get(['image', 'label']) return image, label# Data augementation(Only using in training data)
#   if run_mode == mox.ModeKeys.TRAIN:
#     image = tf.image.random_flip_left_right(image)
#     image = tf.image.random_flip_up_down(image)
#     image = tf.image.rot90(image, k=tf.random_uniform(shape=(), maxval=3, minval=0, dtype=tf.int32)) # 定义CNN模型,不多说,和keras模式差不多
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 = 256, 128, 64, 128# Classification Model
def model_v1(images, run_mode): is_training = (run_mode == mox.ModeKeys.TRAIN) # Conv Layer 1 x = layers.Conv2D(f1, k1, c1, padding='SAME', activation=tf.nn.relu, input_shape=(IMAGE_SIZE, IMAGE_SIZE, CHANNELS))(images) x = layers.MaxPool2D(strides=s1, padding='SAME')(x) x = layers.Dropout(0.5)(x, training=is_training) # Conv Layer 2 x = layers.Conv2D(f2, k2, c2, padding='SAME', activation=tf.nn.relu)(x) x = layers.MaxPool2D(strides=s2, padding='SAME')(x) x = layers.Dropout(0.5)(x, training=is_training)# Conv Layer 3 x = layers.Conv2D(f3, k3, c3, padding='SAME', activation=tf.nn.relu)(x) x = layers.MaxPool2D(strides=s3, padding='SAME')(x) x = layers.Dropout(0.5)(x, training=is_training)# Conv Layer 4 x = layers.Conv2D(f4, k4, c4, padding='SAME', activation=tf.nn.relu)(x) x = layers.MaxPool2D(strides=s4, padding='SAME')(x) x = layers.Dropout(0.5)(x, training=is_training)# Flatten the data for upcoming dense layers x = layers.Flatten()(x) # Dense Layers x = layers.Dense(fc1, activation=tf.nn.relu)(x) x = layers.Dropout(0.2)(x, training=is_training) # Dense Layer 2 x = layers.Dense(fc2, activation=tf.nn.relu)(x) x = layers.Dropout(0.2)(x, training=is_training) # Sigmoid Layer logits =layers.Dense(2)(x) return logits # 定义model函数,这里是核心部分,从input_fn得到的数据在这里与model_fn发生反应,
# 通过mox.ModelSpec打印信息或者输出信息,与keras不同的是,这里使用softmax以及one-hot编码,sigmoid应该也是可以的
def model_fn(inputs, run_mode, **kwargs): # In train or eval, id_or_labels represents labels. In predict, id_or_labels represents id. if run_mode == mox.ModeKeys.PREDICT:images = inputs[0]else:images, labels = inputs# Reshape angles from [batch_size] to [batch_size, 1] # Apply your version of model logits = model_v1(images, run_mode) if run_mode == mox.ModeKeys.PREDICT: logits = tf.nn.softmax(logits) model_spec = mox.ModelSpec(output_info={'logits': logits}) else: labels_one_hot = slim.one_hot_encoding(labels, 2) loss = tf.losses.softmax_cross_entropy( logits=logits, onehot_labels=labels_one_hot) model_spec = mox.ModelSpec(loss=loss, log_info={'loss': loss}) return model_spec # 这里对应model_fn的output_info,将logits[1]即dog的概率保存到DataFrame中,之后写入
def output_fn(outputs): global submission for output in outputs: for logits in output['logits']: # Get the probability of label==1 label = logits[1] df = pd.DataFrame([label], columns=['label']) submission = submission.append(df) # 主函数,根据创建作业时指定的is_training决定运行哪个方法,True对应训练,False对应eval和test
if __name__ == '__main__': # In training mode, using max_number_of_steps to control the epochs# Else, only run one epoch in eval and test mode.if flags.is_training: mox.run(input_fn=input_fn, model_fn=model_fn, optimizer_fn=mox.get_optimizer_fn(name='adam', learning_rate=0.0001), run_mode=mox.ModeKeys.TRAIN, batch_size=flags.batch_size, log_dir=flags.log_dir, max_number_of_steps=steps_per_epoch * 150, # 这里与训练次数相关,自行修改log_every_n_steps=20, save_summary_steps=50, save_model_secs=120) else: mox.run(input_fn=input_fn, model_fn=model_fn, run_mode=mox.ModeKeys.EVAL, batch_size=5, log_every_n_steps=1, max_number_of_steps=int(NUM_SAMPLES_EVAL / 5), checkpoint_path=flags.log_dir) mox.run(input_fn=input_fn, output_fn=output_fn, model_fn=model_fn, run_mode=mox.ModeKeys.PREDICT, batch_size=20,      # 这个地方很关键,必须为test size能整除的数,12500/20,ok,否则会丢失一部分测试数据max_number_of_steps=int(NUM_SAMPLES_TEST / 20),  # 对应上面log_every_n_steps=50, output_every_n_steps=1,   # 这个地方必须为1,否则数据无法存入DataFrame中checkpoint_path=flags.log_dir) # Write results to file. tf.gfile allow writing file to EBS/s3 submission_file = os.path.join(flags.log_dir, 'submission.csv') print('start to write!!!!!')print('info: ', submission.label.values[:10])result = submission.to_csv(path_or_buf=None, index=False) with tf.gfile.Open(submission_file, 'w') as f: f.write(result)print('Success!!!')

经过上面的处理,并不能得到直接可以上传到kaggle的数据,因为我偷懒了,这个csv文件没有id列,所以最后你还需要再加工一下,很简单

结果及分析

使用image size为64的情况

Loss:


Score:

使用image size为128的情况

Loss:

Score:

  1. 在CNN不变的情况下,128大小的训练可以达到更低的损失,但是似乎结果并不比64好,而且与keras对比,似乎这个训练过程中有过拟合的问题,减少max_number_of_steps应该能得到更好的效果;
  2. 使用GPU的速度可快多了,最初的keras使用CPU跑了10小时以上,使用4个GPU可以在几十分钟内跑完更多轮的数据,效果相当的好。

总结

  1. 进行图片识别时基本的方式是使用卷积神经网络,所以使用基于tensorflow的keras可以迅速搭建一个卷积神经网络。
  2. 使用CNN的过程中可能会遇到内存不够的情况,一方面可以考虑优化CNN结构,另一方面可以考虑使用vgg16等已经训练好的模型加上自己的模型进行调试。
  3. 使用华为云进行开发的过程中会遇到一些问题,比如读取图片的方式被限定,tensorflow1.8版本model使用dataset会报错,文件写入的方式被限定,notebook意外断开连接等等。
  4. 使用华为云很方便,基于一个云平台基本可以完成所有的机器学习开发,而且提供了不少的学习工具,还是很实用的。
  5. 希望华为云可以提供更加直接的云计算平台使用方式,就我所想的应该是提供一个可以ssh的服务器,这样代码迁移更加方便。

华为云深度学习kaggle猫狗识别相关推荐

  1. 【深度学习】猫狗识别TensorFlow2实验报告

    实验二:猫狗识别 一.实验目的 利用深度学习实现猫狗动物识别,采用Kaggle提供的公开数据集,训练深度学习模型,对测试集猫狗中的图片准确分类.通过该实验掌握深度学习中基本的CV处理过程. 二.实验原 ...

  2. 使用深度学习分类猫狗图片

    使用深度学习分类猫狗图片 前言 一.下载数据 二.构建网络 三.数据预处理 四.使用数据增强 总结 前言 本文将介绍如何使用较少的数据从头开始训练一个新的深度学习模型.首先在一个2000个训练样本上训 ...

  3. Tensorflow实现kaggle猫狗识别(循序渐进进行网络设计)

    这篇是tensorflow版本,pytorch版本会在下一篇博客给出 友情提示:尽量上GPU,博主CPU上跑一个VGG16花了1.5h... Tensorflow实现kaggle猫狗识别 数据集获取 ...

  4. MoXing——华为云深度学习服务提供的网络模型开发API

    序言:MoXing是华为云深度学习服务提供的网络模型开发API.相对于TensorFlow和MXNet等原生API而言,MoXing API让模型的代码编写更加简单,而且能够自动获取高性能的分布式执行 ...

  5. PyTorch深度学习实战 | 猫狗分类

    本文内容使用TensorFlow和Keras建立一个猫狗图片分类器. 图1 猫狗图片 01.安装TensorFlow和Keras库 TensorFlow是一个采用数据流图(data flow grap ...

  6. pytorch实现kaggle猫狗识别(超详细)

    kaggle是一个为开发商和数据科学家提供举办机器学习竞赛.托管数据库.编写和分享代码的平台,在这上面有非常多的好项目.好资源可供机器学习.深度学习爱好者学习之用.碰巧最近入门了一门非常的深度学习框架 ...

  7. 从零开始学keras之kaggle猫狗识别分类器

    使用很少的数据来训练一个图像分类模型,这是很常见的情况,如果你要从事计算机视觉方面的职业,很可能会在实践中遇到这种情况."很少的"样本可能是几百张图像,也可能是几万张图像.来看一个 ...

  8. python猫狗识别课程设计_pytorch实现kaggle猫狗识别

    # 创建模型 class Net(nn.Module): def __init__(self): super(Net, self).__init__() self.conv1 = nn.Conv2d( ...

  9. 深度学习实现猫狗分类

    本文使用vgg网络实现对猫狗分类. 可以当做图像分类的一个baseline. 一.前期工作 数据:直接到kaggle上下载相应的数据集即可. 1.导入模块 # 数据import torchfrom t ...

最新文章

  1. java触发器如何创建表_在java 中执行触发器代码、创表语句
  2. Redis架构第二天:CenterOS集群、RDB和AOF、主从复制架构实践
  3. hana::detail::variadic::drop_into用法的测试程序
  4. Spark学习之Spark Streaming
  5. r语言echarts画箱线图_R语言之数据可视化---交互式图表recharts
  6. 【华为云 ModelArts-Lab AI实战营】第二期
  7. 平时有没有使用xml和json
  8. ASP.NET MVC 3.0(十二): MVC 3.0 使用自定义的Html控件
  9. jy-12-SPRINGMYBATIS02——学子商城-@成恒
  10. 交友约会APP源码大家有吗
  11. 从技术问题变成RPWT -----------------猛禽
  12. elementUI使用el-tabs时,页面崩溃卡死问题
  13. 企业实践|分布式系统可观测性之应用业务指标监控
  14. 我与北窗青年的2020丶
  15. Oracle Linux网卡参数默认设置导致ORA-603
  16. PAT乙级1040:有几个PAT (25)
  17. Python画一个内部没有边线的五角星
  18. 网卡属性中的巨帧、巨型帧、Jumbo Frame
  19. 打麻将要诀,送给以前常输的你
  20. 国家级区块链基础设施BSN推出BSN-DDC以支持部署NFT

热门文章

  1. python Re模块学习
  2. 同济大学的计算机保研率,同济大学2020届保研率:27.7%
  3. AlexNet网络介绍
  4. android分辨率 尺寸 dpi换算
  5. 哈希算法SHA1,SHA256,SHA384,SHA512
  6. 【Unity 知识点】Unity 如何查找被隐藏的游戏对象
  7. svg文件上传公众号生成微信链接
  8. 轩逸酷我音乐显示服务器错误,第14代轩逸车机系统体验:基本满足日常需求 随车流量模糊不清...
  9. 【Git】git did not exit cleanly (exit code 1) 异常处理
  10. 通达信版弘历软件指标_通达信获利分析仿弘历软件的六彩神龙指标公式-通达信公式...