本月1日起,上海正式开始了“史上最严“垃圾分类的规定,扔错垃圾最高可罚200元。全国其它46个城市也要陆续步入垃圾分类新时代。各种被垃圾分类逼疯的段子在社交媒体上层出不穷。
其实从人工智能的角度看垃圾分类就是图像处理中图像分类任务的一种应用,而这在2012年以来的imagenet图像分类任务的评比中,senet模型以top-5测试集回归2.25%错误率的成绩可谓是技压群雄,堪称目前最强的图像分类器。
笔者刚刚还到senet的创造者momenta公司的网站上看了一下,他们最新的方向已经是3d物体识别和标定了,效果如下:
可以说他们提出的senet进行垃圾图像处理是完全没问题的。
senet简介
senet的是由momenta和牛津大学共同提出的一种基于挤压(squeeze)和激励(excitation)的模型,每个模块通过“挤压”操作嵌入来自全局感受野的信息,并且通过“激励”操作选择性地诱导响应增强。我们可以看到历年的imagenet冠军基本都是在使用加大模型数量和连接数量的方式来提高精度,而senet在这种”大力出奇迹”的潮流下明显是一股清流。其论文地址如下:http://openaccess.thecvf.com/content_cvpr_2018/papers/hu_squeeze-and-excitation_networks_cvpr_2018_paper.pdf
其具体原理说明如下:
sequeeze:对 c×h×w 进行 global average pooling,得到 1×1×c 大小的特征图,这个特征图可以理解为具有全局感受野。翻译论文原文来说:将每个二维的特征通道变成一个实数,这个实数某种程度上具有全局的感受野,并且输出的维度和输入的特征通道数相匹配。它表征着在特征通道上响应的全局分布,而且使得靠近输入的层也可以获得全局的感受野。
excitation :使用一个全连接神经网络,对 sequeeze 之后的结果做一个非线性变换。它的机制一个类似于循环神经网络中的门。通过参数 w 来为每个特征通道生成权重,其中参数 w 被学习用来显式地建模特征通道间的相关性。
特征重标定:使用 excitation 得到的结果作为权重,乘到输入特征上。将excitation输出的权重可以认为是特征通道的重要性反应,逐通道加权到放到先前的特征上,完成对原始特征的重标定。
其模型架构如下:
senet 构造非常简单,而且很容易被部署,不需要引入新的函数或者层。其caffe模型可以通过百度下载(https://pan.baidu.com/s/1o7hdfae?errno=0&errmsg=auth%20login%20sucess&&bduss=&ssnerror=0&traceid=)
senet的运用
如果读者布署有caffe那么直接下载刚刚的模型直接load进来就可以使用了。如果没有装caffe而装了tensorflow也没关系,我们刚刚说了senet没有引入新的函数和层,很方便用tensorflow实现。
下载图像集:经笔者各方查找发现了这个数据集,虽然不大也没有发挥出senet的优势,不过也方便使用:
https://raw.githubusercontent.com/garythung/trashnet/master/data/dataset-resized.zip
建立senet模型:使用tensorflow建立的模型在github上也有开源项目了,网址如下:https://github.com/taki0112/senet-tensorflow,只是他使用的是cifar10数据集,不过这也没关系,只需要在gitclone以下将其cifar10.py中的prepare_data函数做如下修改即可。
1defprepare_data(): 2print(======loadingdata======) 3download_data() 4data_dir='e:/test/' 5#data_dir='./cifar-10-batches-py'#改为你的文件侠 6image_dim=image_size*image_size*img_channels 7#meta=unpickle(data_dir+'/batches.meta')#本数据集不使用meta文件分类,故需要修改 8label_names=['cardboard','glass','metal','trash','paper','plastic'] 9label_count=len(label_names)10#train_files=['data_batch_%d'%dfordinrange(1,6)]11train_files=[data_dir+sforsinlabel_names]#改为12train_data,train_labels=load_data(train_files,data_dir,label_count)13test_data,test_labels=load_data(['test_batch'],data_dir,label_count)1415print(traindata:,np.shape(train_data),np.shape(train_labels))16print(testdata:,np.shape(test_data),np.shape(test_labels))17print(======loadfinished======)1819print(======shufflingdata======)20indices=np.random.permutation(len(train_data))21train_data=train_data[indices]22train_labels=train_labels[indices]23print(======preparefinished======)2425returntrain_data,train_labels,test_data,test_labels
其最主要的建模代码如下,其主要工作就是将senet的模型结构实现一下即可:
1importtensorflowastf 2fromtflearn.layers.convimportglobal_avg_pool 3fromtensorflow.contrib.layersimportbatch_norm,flatten 4fromtensorflow.contrib.frameworkimportarg_scope 5fromcifar10import* 6importnumpyasnp 7 8weight_decay=0.0005 9momentum=0.9 10 11init_learning_rate=0.1 12 13reduction_ratio=4 14 15batch_size=128 16iteration=391 17#128*391~50,000 18 19test_iteration=10 20 21total_epochs=100 22 23defconv_layer(input,filter,kernel,stride=1,padding='same',layer_name=conv,activation=true): 24withtf.name_scope(layer_name): 25network=tf.layers.conv2d(inputs=input,use_bias=true,filters=filter,kernel_size=kernel,strides=stride,padding=padding) 26ifactivation: 27network=relu(network) 28returnnetwork 29 30deffully_connected(x,units=class_num,layer_name='fully_connected'): 31withtf.name_scope(layer_name): 32returntf.layers.dense(inputs=x,use_bias=true,units=units) 33 34defrelu(x): 35returntf.nn.relu(x) 36 37defsigmoid(x): 38returntf.nn.sigmoid(x) 39 40defglobal_average_pooling(x): 41returnglobal_avg_pool(x,name='global_avg_pooling') 42 43defmax_pooling(x,pool_size=[3,3],stride=2,padding='valid'): 44returntf.layers.max_pooling2d(inputs=x,pool_size=pool_size,strides=stride,padding=padding) 45 46defbatch_normalization(x,training,scope): 47witharg_scope([batch_norm], 48scope=scope, 49updates_collections=none, 50decay=0.9, 51center=true, 52scale=true, 53zero_debias_moving_mean=true): 54returntf.cond(training, 55lambda:batch_norm(inputs=x,is_training=training,reuse=none), 56lambda:batch_norm(inputs=x,is_training=training,reuse=true)) 57 58defconcatenation(layers): 59returntf.concat(layers,axis=3) 60 61defdropout(x,rate,training): 62returntf.layers.dropout(inputs=x,rate=rate,training=training) 63 64defevaluate(sess): 65test_acc=0.0 66test_loss=0.0 67test_pre_index=0 68add=1000 69 70foritinrange(test_iteration): 71test_batch_x=test_x[test_pre_index:test_pre_index+add] 72test_batch_y=test_y[test_pre_index:test_pre_index+add] 73test_pre_index=test_pre_index+add 74 75test_feed_dict={ 76x:test_batch_x, 77label:test_batch_y, 78learning_rate:epoch_learning_rate, 79training_flag:false 80} 81 82loss_,acc_=sess.run([cost,accuracy],feed_dict=test_feed_dict) 83 84test_loss+=loss_ 85test_acc+=acc_ 86 87test_loss/=test_iteration#averageloss 88test_acc/=test_iteration#averageaccuracy 89 90summary=tf.summary(value=[tf.summary.value(tag='test_loss',simple_value=test_loss), 91tf.summary.value(tag='test_accuracy',simple_value=test_acc)]) 92 93returntest_acc,test_loss,summary 94 95classse_inception_resnet_v2(): 96def__init__(self,x,training): 97self.training=training 98self.model=self.build_senet(x) 99100defstem(self,x,scope):101withtf.name_scope(scope):102x=conv_layer(x,filter=32,kernel=[3,3],stride=2,padding='valid',layer_name=scope+'_conv1')103x=conv_layer(x,filter=32,kernel=[3,3],padding='valid',layer_name=scope+'_conv2')104block_1=conv_layer(x,filter=64,kernel=[3,3],layer_name=scope+'_conv3')105106split_max_x=max_pooling(block_1)107split_conv_x=conv_layer(block_1,filter=96,kernel=[3,3],stride=2,padding='valid',layer_name=scope+'_split_conv1')108x=concatenation([split_max_x,split_conv_x])109110split_conv_x1=conv_layer(x,filter=64,kernel=[1,1],layer_name=scope+'_split_conv2')111split_conv_x1=conv_layer(split_conv_x1,filter=96,kernel=[3,3],padding='valid',layer_name=scope+'_split_conv3')112113split_conv_x2=conv_layer(x,filter=64,kernel=[1,1],layer_name=scope+'_split_conv4')114split_conv_x2=conv_layer(split_conv_x2,filter=64,kernel=[7,1],layer_name=scope+'_split_conv5')115split_conv_x2=conv_layer(split_conv_x2,filter=64,kernel=[1,7],layer_name=scope+'_split_conv6')116split_conv_x2=conv_layer(split_conv_x2,filter=96,kernel=[3,3],padding='valid',layer_name=scope+'_split_conv7')117118x=concatenation([split_conv_x1,split_conv_x2])119120split_conv_x=conv_layer(x,filter=192,kernel=[3,3],stride=2,padding='valid',layer_name=scope+'_split_conv8')121split_max_x=max_pooling(x)122123x=concatenation([split_conv_x,split_max_x])124125x=batch_normalization(x,training=self.training,scope=scope+'_batch1')126x=relu(x)127128returnx129130definception_resnet_a(self,x,scope):131withtf.name_scope(scope):132init=x133134split_conv_x1=conv_layer(x,filter=32,kernel=[1,1],layer_name=scope+'_split_conv1')135136split_conv_x2=conv_layer(x,filter=32,kernel=[1,1],layer_name=scope+'_split_conv2')137split_conv_x2=conv_layer(split_conv_x2,filter=32,kernel=[3,3],layer_name=scope+'_split_conv3')138139split_conv_x3=conv_layer(x,filter=32,kernel=[1,1],layer_name=scope+'_split_conv4')140split_conv_x3=conv_layer(split_conv_x3,filter=48,kernel=[3,3],layer_name=scope+'_split_conv5')141split_conv_x3=conv_layer(split_conv_x3,filter=64,kernel=[3,3],layer_name=scope+'_split_conv6')142143x=concatenation([split_conv_x1,split_conv_x2,split_conv_x3])144x=conv_layer(x,filter=384,kernel=[1,1],layer_name=scope+'_final_conv1',activation=false)145146x=x*0.1147x=init+x148149x=batch_normalization(x,training=self.training,scope=scope+'_batch1')150x=relu(x)151152returnx153154definception_resnet_b(self,x,scope):155withtf.name_scope(scope):156init=x157158split_conv_x1=conv_layer(x,filter=192,kernel=[1,1],layer_name=scope+'_split_conv1')159160split_conv_x2=conv_layer(x,filter=128,kernel=[1,1],layer_name=scope+'_split_conv2')161split_conv_x2=conv_layer(split_conv_x2,filter=160,kernel=[1,7],layer_name=scope+'_split_conv3')162split_conv_x2=conv_layer(split_conv_x2,filter=192,kernel=[7,1],layer_name=scope+'_split_conv4')163164x=concatenation([split_conv_x1,split_conv_x2])165x=conv_layer(x,filter=1152,kernel=[1,1],layer_name=scope+'_final_conv1',activation=false)166#1154167x=x*0.1168x=init+x169170x=batch_normalization(x,training=self.training,scope=scope+'_batch1')171x=relu(x)172173returnx174175definception_resnet_c(self,x,scope):176withtf.name_scope(scope):177init=x178179split_conv_x1=conv_layer(x,filter=192,kernel=[1,1],layer_name=scope+'_split_conv1')180181split_conv_x2=conv_layer(x,filter=192,kernel=[1,1],layer_name=scope+'_split_conv2')182split_conv_x2=conv_layer(split_conv_x2,filter=224,kernel=[1,3],layer_name=scope+'_split_conv3')183split_conv_x2=conv_layer(split_conv_x2,filter=256,kernel=[3,1],layer_name=scope+'_split_conv4')184185x=concatenation([split_conv_x1,split_conv_x2])186x=conv_layer(x,filter=2144,kernel=[1,1],layer_name=scope+'_final_conv2',activation=false)187#2048188x=x*0.1189x=init+x190191x=batch_normalization(x,training=self.training,scope=scope+'_batch1')192x=relu(x)193194returnx195196defreduction_a(self,x,scope):197withtf.name_scope(scope):198k=256199l=256200m=384201n=384202203split_max_x=max_pooling(x)204205split_conv_x1=conv_layer(x,filter=n,kernel=[3,3],stride=2,padding='valid',layer_name=scope+'_split_conv1')206207split_conv_x2=conv_layer(x,filter=k,kernel=[1,1],layer_name=scope+'_split_conv2')208split_conv_x2=conv_layer(split_conv_x2,filter=l,kernel=[3,3],layer_name=scope+'_split_conv3')209split_conv_x2=conv_layer(split_conv_x2,filter=m,kernel=[3,3],stride=2,padding='valid',layer_name=scope+'_split_conv4')210211x=concatenation([split_max_x,split_conv_x1,split_conv_x2])212213x=batch_normalization(x,training=self.training,scope=scope+'_batch1')214x=relu(x)215216returnx217218defreduction_b(self,x,scope):219withtf.name_scope(scope):220split_max_x=max_pooling(x)221222split_conv_x1=conv_layer(x,filter=256,kernel=[1,1],layer_name=scope+'_split_conv1')223split_conv_x1=conv_layer(split_conv_x1,filter=384,kernel=[3,3],stride=2,padding='valid',layer_name=scope+'_split_conv2')224225split_conv_x2=conv_layer(x,filter=256,kernel=[1,1],layer_name=scope+'_split_conv3')226split_conv_x2=conv_layer(split_conv_x2,filter=288,kernel=[3,3],stride=2,padding='valid',layer_name=scope+'_split_conv4')227228split_conv_x3=conv_layer(x,filter=256,kernel=[1,1],layer_name=scope+'_split_conv5')229split_conv_x3=conv_layer(split_conv_x3,filter=288,kernel=[3,3],layer_name=scope+'_split_conv6')230split_conv_x3=conv_layer(split_conv_x3,filter=320,kernel=[3,3],stride=2,padding='valid',layer_name=scope+'_split_conv7')231232x=concatenation([split_max_x,split_conv_x1,split_conv_x2,split_conv_x3])233234x=batch_normalization(x,training=self.training,scope=scope+'_batch1')235x=relu(x)236237returnx238239defsqueeze_excitation_layer(self,input_x,out_dim,ratio,layer_name):240withtf.name_scope(layer_name):241242243squeeze=global_average_pooling(input_x)244245excitation=fully_connected(squeeze,units=out_dim/ratio,layer_name=layer_name+'_fully_connected1')246excitation=relu(excitation)247excitation=fully_connected(excitation,units=out_dim,layer_name=layer_name+'_fully_connected2')248excitation=sigmoid(excitation)249250excitation=tf.reshape(excitation,[-1,1,1,out_dim])251scale=input_x*excitation252253returnscale254255defbuild_senet(self,input_x):256input_x=tf.pad(input_x,[[0,0],[32,32],[32,32],[0,0]])257#size32->96258print(np.shape(input_x))259#onlycifar10architecture260261x=self.stem(input_x,scope='stem')262263foriinrange(5):264x=self.inception_resnet_a(x,scope='inception_a'+str(i))265channel=int(np.shape(x)[-1])266x=self.squeeze_excitation_layer(x,out_dim=channel,ratio=reduction_ratio,layer_name='se_a'+str(i))267268x=self.reduction_a(x,scope='reduction_a')269270channel=int(np.shape(x)[-1])271x=self.squeeze_excitation_layer(x,out_dim=channel,ratio=reduction_ratio,layer_name='se_a')272273foriinrange(10):274x=self.inception_resnet_b(x,scope='inception_b'+str(i))275channel=int(np.shape(x)[-1])276x=self.squeeze_excitation_layer(x,out_dim=channel,ratio=reduction_ratio,layer_name='se_b'+str(i))277278x=self.reduction_b(x,scope='reduction_b')279280channel=int(np.shape(x)[-1])281x=self.squeeze_excitation_layer(x,out_dim=channel,ratio=reduction_ratio,layer_name='se_b')282283foriinrange(5):284x=self.inception_resnet_c(x,scope='inception_c'+str(i))285channel=int(np.shape(x)[-1])286x=self.squeeze_excitation_layer(x,out_dim=channel,ratio=reduction_ratio,layer_name='se_c'+str(i))287288289#channel=int(np.shape(x)[-1])290#x=self.squeeze_excitation_layer(x,out_dim=channel,ratio=reduction_ratio,layer_name='se_c')291292x=global_average_pooling(x)293x=dropout(x,rate=0.2,training=self.training)294x=flatten(x)295296x=fully_connected(x,layer_name='final_fully_connected')297returnx298299300train_x,train_y,test_x,test_y=prepare_data()301train_x,test_x=color_preprocessing(train_x,test_x)302303304#image_size=32,img_channels=3,class_num=10incifar10305x=tf.placeholder(tf.float32,shape=[none,image_size,image_size,img_channels])306label=tf.placeholder(tf.float32,shape=[none,class_num])307308training_flag=tf.placeholder(tf.bool)309310311learning_rate=tf.placeholder(tf.float32,name='learning_rate')312313logits=se_inception_resnet_v2(x,training=training_flag).model314cost=tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=label,logits=logits))315316l2_loss=tf.add_n([tf.nn.l2_loss(var)forvarintf.trainable_variables()])317optimizer=tf.train.momentumoptimizer(learning_rate=learning_rate,momentum=momentum,use_nesterov=true)318train=optimizer.minimize(cost+l2_loss*weight_decay)319320correct_prediction=tf.equal(tf.argmax(logits,1),tf.argmax(label,1))321accuracy=tf.reduce_mean(tf.cast(correct_prediction,tf.float32))322323saver=tf.train.saver(tf.global_variables())324325withtf.session()assess:326ckpt=tf.train.get_checkpoint_state('./model')327ifckptandtf.train.checkpoint_exists(ckpt.model_checkpoint_path):328saver.restore(sess,ckpt.model_checkpoint_path)329else:330sess.run(tf.global_variables_initializer())331332summary_writer=tf.summary.filewriter('./logs',sess.graph)333334epoch_learning_rate=init_learning_rate335forepochinrange(1,total_epochs+1):336ifepoch%30==0:337epoch_learning_rate=epoch_learning_rate/10338339pre_index=0340train_acc=0.0341train_loss=0.0342343forstepinrange(1,iteration+1):344ifpre_index+batch_size<50000:345batch_x=train_x[pre_index:pre_index+batch_size]346batch_y=train_y[pre_index:pre_index+batch_size]347else:348batch_x=train_x[pre_index:]349batch_y=train_y[pre_index:]350351batch_x=data_augmentation(batch_x)352353train_feed_dict={354x:batch_x,355label:batch_y,356learning_rate:epoch_learning_rate,357training_flag:true358}359360_,batch_loss=sess.run([train,cost],feed_dict=train_feed_dict)361batch_acc=accuracy.eval(feed_dict=train_feed_dict)362363train_loss+=batch_loss364train_acc+=batch_acc365pre_index+=batch_size366367368train_loss/=iteration#averageloss369train_acc/=iteration#averageaccuracy370371train_summary=tf.summary(value=[tf.summary.value(tag='train_loss',simple_value=train_loss),372tf.summary.value(tag='train_accuracy',simple_value=train_acc)])373374test_acc,test_loss,test_summary=evaluate(sess)375376summary_writer.add_summary(summary=train_summary,global_step=epoch)377summary_writer.add_summary(summary=test_summary,global_step=epoch)378summary_writer.flush()379380line=epoch:%d/%d,train_loss:%.4f,train_acc:%.4f,test_loss:%.4f,test_acc:%.4f%(381epoch,total_epochs,train_loss,train_acc,test_loss,test_acc)382print(line)383384withopen('logs.txt','a')asf:385f.write(line)386387saver.save(sess=sess,save_path='./model/inception_resnet_v2.ckpt')
其实使用senet做垃圾分类真是大才小用了,不过大家也可以感受一下他的实力强大。
SPI/I2C/USART通讯方式的特点
小米MIX2怎么样?小米MIX2评测:小米MIX2真机上手优缺点分析
中国芯支撑云存储 国产化替代切实可行
一亿像素有何看头 更高像素的意义是什么
AMD、英伟达在GPU 市场的厮杀现状
从人工智能的角度看垃圾分类
NUAIR加入AiRXOS,扩大无人机系统交通管理解决方案的应用
Holtek推出新一代的BS83xxxC系列Touch Flash MCU
硬朗造型+智能科技感 北通蝙蝠4游戏手柄即将震撼来临!
DFRobot DF9GMS 180° 微型舵机介绍
民爆光电的创业板IPO申请已获受理
华为汪涛:智慧教育,育见未来
关于IR_CUT滤光片切换器技术分析介绍
用数字线程连接物联网芯片
两只场效应管KW25N120E怎么做逆变器
DataEmpowerment解决方案
盘点:三星S8发布会上没有讲到的黑科技,苹果也要抖三抖!
泛在电力物联网云计算在各行业中的广泛应用介绍
RC电路波形全面分析汇总
三星折叠屏手机概念图曝光