前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【cntk速成】cntk图像分类从模型自定义到测试

【cntk速成】cntk图像分类从模型自定义到测试

作者头像
用户1508658
发布2019-07-26 16:52:36
4490
发布2019-07-26 16:52:36
举报
文章被收录于专栏:有三AI有三AI

01CNTK是什么

地址:https://github.com/Microsoft/CNTK

CNTK是微软开源的深度学习工具包,它通过有向图将神经网络描述为一系列计算步骤。在有向图中,叶节点表示输入值或网络参数,而其他节点表示其输入上的矩阵运算。

CNTK允许用户非常轻松地实现和组合流行的模型,包括前馈DNN,卷积网络(CNN)和循环网络(RNN / LSTM)。与目前大部分框架一样,实现了自动求导,利用随机梯度下降方法进行优化。

cntk有什么特点呢?

1.1 性能较高

按照其官方的说法,比其他的开源框架性能都更高。

笔者在实际进行实验的时候,确实也发现它的训练比较快。

1.2 适合做语音

CNTK本就是微软语音团队开源的,自然是更合适做语音任务,使用RNN等模型,以及在时空尺度分别进行卷积非常容易

当然,现在的背靠python的这些框架已经大同小异,未来实现大一统并非不可能。

02CNTK模型训练

pip安装一条命令即可,可以选择安装cpu或者gpu版本。

pip install cntk/cntk-gpu。

接下来就是数据的准备,模型的定义,结果的保存与分析。

在此之前,我们先看官方的分类案例,直观感受一下,代码比较长。

from __future__ import print_function

import numpy as np

import cntk as C

from cntk.learners import sgd

from cntk.logging import ProgressPrinter

from cntk.layers import Dense, Sequential

def generate_random_data(sample_size, feature_dim, num_classes):

# Create synthetic data using NumPy. Y = np.random.randint(size=(sample_size, 1), low=0, high=num_classes) # Make sure that the data is separable X = (np.random.randn(sample_size, feature_dim) + 3) * (Y + 1) X = X.astype(np.float32) # converting class 0 into the vector "1 0 0", # class 1 into vector "0 1 0", ... class_ind = [Y == class_number for class_number in range(num_classes)] Y = np.asarray(np.hstack(class_ind), dtype=np.float32) return X, Ydef ffnet(): inputs = 2 outputs = 2 layers = 2 hidden_dimension = 50 # input variables denoting the features and label data features = C.input_variable((inputs), np.float32) label = C.input_variable((outputs), np.float32) # Instantiate the feedforward classification model my_model = Sequential ([ Dense(hidden_dimension, activation=C.sigmoid), Dense(outputs)]) z = my_model(features) ce = C.cross_entropy_with_softmax(z, label) pe = C.classification_error(z, label) # Instantiate the trainer object to drive the model training lr_per_minibatch = C.learning_parameter_schedule(0.125) progress_printer = ProgressPrinter(0) trainer = C.Trainer(z, (ce, pe), [sgd(z.parameters, lr=lr_per_minibatch)], [progress_printer]) # Get minibatches of training data and perform model training minibatch_size = 25 num_minibatches_to_train = 1024 aggregate_loss = 0.0 for i in range(num_minibatches_to_train): train_features, labels = generate_random_data(minibatch_size, inputs, outputs) # Specify the mapping of input variables in the model to actual minibatch data to be trained with trainer.train_minibatch({features : train_features, label : labels}) sample_count = trainer.previous_minibatch_sample_count aggregate_loss += trainer.previous_minibatch_loss_average * sample_count last_avg_error = aggregate_loss / trainer.total_number_of_samples_seen test_features, test_labels = generate_random_data(minibatch_size, inputs, outputs) avg_error = trainer.test_minibatch({features : test_features, label : test_labels}) print(' error rate on an unseen minibatch: {}'.format(avg_error)) return last_avg_error, avg_errornp.random.seed(98052)ffnet()

上面就是一个两层的全连接神经网络,使用input_variable封装数据,使用Sequential定义模型,使用train_minibatch({features : train_features, label : labels})来feed数据,与tf,pytorch等框架都是一样的,的确是没有什么好说的。

2.1 数据读取

这里需要用到接口,io.ImageDeserializer与C.io.StreamDefs,C.io.StreamDef。

它可以直接输入如下格式的txt文件用于图像分类问题。

../../../../datas/mouth/1/182smile.jpg1

../../../../datas/mouth/1/435smile.jpg1

../../../../datas/mouth/0/40neutral.jpg0

../../../../datas/mouth/1/206smile.jpg1

注意上面采用的分隔符是'\t',这一点与MXNet相同,与caffe不同,完整的解析代码如下:

C.io.MinibatchSource(C.io.ImageDeserializer(map_file, C.io.StreamDefs(

features = C.io.StreamDef(field='image', transforms=transforms),

labels = C.io.StreamDef(field='label', shape=num_classes)

)))

在对图像数据进行封装的时候,添加了transform,所以可以在这里进行数据预处理操作。

常用的裁剪与缩放如下:

transform.crop(crop_type='randomside', side_ratio=0.8)

transform.scale(width=image_width, height=image_height, channels=num_channels, interpolations='linear')

C.io.MinibatchSource的返回就是数据指针,可以直接用于训练。

2.2 网络定义

与tensorflow和pytorch颇为相似,如下

def simpleconv3(input, out_dims): with C.layers.default_options(init=C.glorot_uniform(), activation=C.relu): net = C.layers.Convolution((3,3), 12, pad=True)(input) net = C.layers.MaxPooling((3,3), strides=(2,2))(net) net = C.layers.Convolution((3,3), 24, pad=True)(net) net = C.layers.MaxPooling((3,3), strides=(2,2))(net) net = C.layers.Convolution((3,3), 48, pad=True)(net) net = C.layers.MaxPooling((3,3), strides=(2,2))(net) net = C.layers.Dense(128)(net) net = C.layers.Dense(out_dims, activation=None)(net) return net

2.3 损失函数与分类错误率指标定义

如下,model_func就是上面的net,input_var_norm和label_var分别就是数据和标签。

z = model_func(input_var_norm, out_dims=2)

ce = C.cross_entropy_with_softmax(z, label_var)

pe = C.classification_error(z, label_var)

2.4 训练参数

就是学习率,优化方法,epoch等配置。

epoch_size = 900

minibatch_size = 64

lr_per_minibatch = C.learning_rate_schedule([0.01]*100 + [0.003]*100 + [0.001],

C.UnitType.minibatch, epoch_size)

m = C.momentum_schedule(0.9)

l2_reg_weight = 0.001

learner = C.momentum_sgd(z.parameters,

lr = lr_per_minibatch,

momentum = m,

l2_regularization_weight=l2_reg_weight)

progress_printer = C.logging.ProgressPrinter(tag='Training', num_epochs=max_epochs)

trainer = C.Trainer(z, (ce, pe), [learner], [progress_printer])

注意学习率的配置比较灵活,通过learning_rate_schedule接口,上面的C.learning_rate_schedule([0.01]*100 + [0.003]*100 + [0.001]意思是,在0~100 epoch,使用0.01的学习率,100~100+100 epoch,使用0.003学习率,此后使用0.001学习率。

2.5 训练与保存

使用数据指针的next_minibatch获取训练数据,trainer的train_minibatch进行训练,可以看出cntk非常强调minibatch的概念,实际上学习率和优化方法都可以针对单个样本进行设置。

for epoch in range(max_epochs):

sample_count = 0

while sample_count < epoch_size:

data = reader_train.next_minibatch(min(minibatch_size, epoch_size - sample_count), input_map=input_map)

trainer.train_minibatch(data)

模型的保存就一行代码:

z.save("simpleconv3.dnn")

2.6 可视化

需要可视化的内容不多,就是loss曲线和精度曲线,所以可以直接自己添加代码,用上面的模型训练最后的loss如下,更好参数可自己调。

03CNTK模型测试

测试就是载入模型,做好与训练时同样的预处理操作然后forward就行了。

import *** model_file = sys.argv[1] image_list = sys.argv[2] model = C.load_model(model_file) count = 0 acc = 0 imagepaths = open(image_list,'r').readlines() for imagepath in imagepaths: imagepath,label = imagepath.strip().split('\t') im = Image.open(imagepath) print imagepath print "im size",im.size image_data = np.array(im,dtype=np.float32) image_data = cv2.resize(image_data,(image_width,image_height)) image_data = np.ascontiguousarray(np.transpose(image_data, (2, 0, 1))) output = model.eval({model.arguments[0]:[image_data]})[0] print output print label,np.argmax(np.squeeze(output)) if str(label) == str(np.argmax(np.squeeze(output))): acc = acc + 1 count = count + 1 print "acc=",float(acc) / float(count)

最终模型训练集准确率91%,测试集准确率88%,大家可以自己去做更多调试。

总结

相比于tensorflow,pytorch,cntk固然是比较小众,但也不失为一个优秀的平台,尤其是对于语音任务,感兴趣大家可以自行体验,代码已经上传至https://github.com/longpeng2008/LongPeng_ML_Course

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-01-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 有三AI 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档