0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

手把手带你进入AI的世界,让你消除对AI技术壁垒过高的恐惧

电子工程师 来源:未知 作者:李倩 2018-11-24 10:49 次阅读

从年初起,几家国际大厂的开发者大会,无论是微软Build、Facebook F8还是稍后的Google I/O,莫不把“AI优先”的大旗扯上云霄。

如果这一波AI大潮只是空喊几句口号,空提几个战略,空有几家炙手可热的创业公司,那当然成不了什么大气候。但风浪之下,我们看到的却是,Google一线的各大业务纷纷改用深度学习,落伍移动时代的微软则已拉起一支近万人的AI队伍。而国内一线大厂的情况,更是把AI牢牢把握住,试图再创高峰。

今天本文将分享一篇AI入门实战的项目经验分享,手把手带你进入AI的世界,让你消除对AI技术壁垒过高的恐惧~

【AI项目实战】多标签图像分类竞赛小试牛刀

初次拿到这个题目,想了想做过了猫狗大战这样的二分类,也做过cifar-10这样的多分类,类似本次比赛的题目多标签图像分类的确没有尝试过。6941个标签,每张图片可能没有标签也可能存在6941个标签,即各个标签之间是不存在互斥关系的,所以最终分类的损失函数不能用softmax而必须要用sigmoid。然后把分类层预测6941个神经元,每个神经元用sigmoid函数返回是否存在某个标签即可。

来蹚下整个流程看看,在jupyter notebook上做得比较乱,但是整个流程还是可以看出来的。深度学习模型用的Keras。

先导入train_csv数据,这里用的是最初版的训练csv文件,img_path里存在地址,后面做了处理。

code

importpandasaspdimportnumpyasnpimportmatplotlib.pyplotasplt%matplotlibinlinefromglobimportglobfromtqdmimporttqdmimportcv2fromPILimportImagetrain_path='visual_china_train.csv'train_df=pd.read_csv(train_path)train_df.head()

codetrain_df.shape#(35000,2)

可以看到总共有35000张训练图片,第一列为图片名称(带地址,需处理),第二列为图片对应标签。

来看下是不是的确只有6941个标签:

code

tags=[]foriinrange(train_df['tags'].shape[0]):fortagintrain_df['tags'].iloc[i].split(','):tags.append(tag)tags=set(tags)len(tags)#6941

事实证明标签总数无误,可以放心大胆地继续进行下去了。

然后我处理了下图片名称,并存到了img_paths列表里。

code

#如果使用的是官方后来更新的visual_china_train.csv,可以直接使用最后一行代码foriinrange(35000):train_df['img_path'].iloc[i]=train_df['img_path'].iloc[i].split('/')[-1]img_paths=list(train_df['img_path'])

定义三个函数,其中:

hash_tag函数读入valid_tags.txt文件,并存入字典,形成索引和标签的对照。

load_ytrain函数读入tag_train.npz文件,并返回训练集的y_train,形式为ndarray,shape为(35000, 6941),即35000张图片和对应标签的one-hot编码。

arr2tag函数将预测结果的y_pred转变成对应的中文标签。(实际上最后还需要做下处理)

code

defhash_tag(filepath):fo=open(filepath,"r",encoding='utf-8')hash_tag={}i=0forlineinfo.readlines():#依次读取每行line=line.strip()#去掉每行头尾空白hash_tag[i]=linei+=1returnhash_tagdefload_ytrain(filepath):y_train=np.load(filepath)y_train=y_train['tag_train']returny_traindefarr2tag(arr):tags=[]foriinrange(arr.shape[0]):tag=[]index=np.where(arr[i]>0.5)index=index[0].tolist()tag=[hash_tag[j]forjinindex]tags.append(tag)returntags

读入valid_tags.txt,并生成索引和标签的映射。

code

filepath="valid_tags.txt"hash_tag=hash_tag(filepath)hash_tag[1]#'0到1个月'

载入y_train

code

y_train=load_ytrain('tag_train.npz')y_train.shape#(35000,6941)

前期准备工作差不多做完了,开始导入训练集。此处有个坑,即原始训练集中存在CMYK格式的图片,传统图片处理一般为RGB格式,所以使用Image库中的convert函数对非RGB格式的图片进行转换。

code

nub_train=5000#可修改,前期尝试少量数据验证模型X_train=np.zeros((nub_train,224,224,3),dtype=np.uint8)i=0forimg_pathinimg_paths[:nub_train]:img=Image.open('train/'+img_path)ifimg.mode!='RGB':img=img.convert('RGB')img=img.resize((224,224))arr=np.asarray(img)X_train[i,:,:,:]=arri+=1

训练集导入完成,来看图片的样子,判断下图片有没有读入错误之类的问题。

code

fig,axes=plt.subplots(6,6,figsize=(20,20))j=0fori,imginenumerate(X_train[:36]):axes[i//6,j%6].imshow(img)j+=1

看样子还不错,go on! 训练集的X_train、y_train都拿到了,分割出验证集。这里要说明一下,官方的y_train里图片名称与X_train里图片名称是对应的所以可以直接分割。

code

fromsklearn.model_selectionimporttrain_test_splitX_train2,X_val,y_train2,y_val=train_test_split(X_train,y_train[:nub_train],test_size=0.2,random_state=2018)

数据准备完成,开始搭建模型。咳咳,先从简单的入手哈,此模型仿tinymind上一次的汉字书法识别大赛中“真的学不会”大佬的结构来搭的,又加了些自己的东西,反正简单模型试试水嘛。

code

fromkeras.layersimport*fromkeras.modelsimport*fromkeras.optimizersimport*fromkeras.callbacksimport*defbn_prelu(x):x=BatchNormalization()(x)x=PReLU()(x)returnxdefbuild_model(out_dims,input_shape=(224,224,3)):inputs_dim=Input(input_shape)x=Lambda(lambdax:x/255.0)(inputs_dim)#在模型里进行归一化预处理x=Conv2D(16,(3,3),strides=(2,2),padding='same')(x)x=bn_prelu(x)x=Conv2D(16,(3,3),strides=(1,1),padding='same')(x)x=bn_prelu(x)x=MaxPool2D(pool_size=(2,2))(x)x=Conv2D(32,(3,3),strides=(1,1),padding='same')(x)x=bn_prelu(x)x=Conv2D(32,(3,3),strides=(1,1),padding='same')(x)x=bn_prelu(x)x=MaxPool2D(pool_size=(2,2))(x)x=Conv2D(64,(3,3),strides=(1,1),padding='same')(x)x=bn_prelu(x)x=MaxPool2D(pool_size=(2,2))(x)x=Conv2D(128,(3,3),strides=(1,1),padding='same')(x)x=bn_prelu(x)x=GlobalAveragePooling2D()(x)dp_1=Dropout(0.5)(x)fc2=Dense(out_dims)(dp_1)fc2=Activation('sigmoid')(fc2)#此处注意,为sigmoid函数model=Model(inputs=inputs_dim,outputs=fc2)returnmodel

看下模型结构:

code

model=build_model(6941)model.summary()_________________________________________________________________Layer(type)OutputShapeParam# =================================================================input_1(InputLayer)(None,224,224,3)0 _________________________________________________________________lambda_1(Lambda)(None,224,224,3)0 _________________________________________________________________conv2d_1(Conv2D)(None,112,112,16)448 _________________________________________________________________batch_normalization_1(Batch(None,112,112,16)64 _________________________________________________________________p_re_lu_1(PReLU)(None,112,112,16)200704 _________________________________________________________________conv2d_2(Conv2D)(None,112,112,16)2320 _________________________________________________________________batch_normalization_2(Batch(None,112,112,16)64 _________________________________________________________________p_re_lu_2(PReLU)(None,112,112,16)200704 _________________________________________________________________max_pooling2d_1(MaxPooling2(None,56,56,16)0 _________________________________________________________________conv2d_3(Conv2D)(None,56,56,32)4640 _________________________________________________________________batch_normalization_3(Batch(None,56,56,32)128 _________________________________________________________________p_re_lu_3(PReLU)(None,56,56,32)100352 _________________________________________________________________conv2d_4(Conv2D)(None,56,56,32)9248 _________________________________________________________________batch_normalization_4(Batch(None,56,56,32)128 _________________________________________________________________p_re_lu_4(PReLU)(None,56,56,32)100352 _________________________________________________________________max_pooling2d_2(MaxPooling2(None,28,28,32)0 _________________________________________________________________conv2d_5(Conv2D)(None,28,28,64)18496 _________________________________________________________________batch_normalization_5(Batch(None,28,28,64)256 _________________________________________________________________p_re_lu_5(PReLU)(None,28,28,64)50176 _________________________________________________________________max_pooling2d_3(MaxPooling2(None,14,14,64)0 _________________________________________________________________conv2d_6(Conv2D)(None,14,14,128)73856 _________________________________________________________________batch_normalization_6(Batch(None,14,14,128)512 _________________________________________________________________p_re_lu_6(PReLU)(None,14,14,128)25088 _________________________________________________________________global_average_pooling2d_1((None,128)0 _________________________________________________________________dropout_1(Dropout)(None,128)0 _________________________________________________________________dense_1(Dense)(None,6941)895389 _________________________________________________________________activation_1(Activation)(None,6941)0 =================================================================Totalparams:1,682,925 Trainableparams:1,682,349 Non-trainableparams:576_________________________________________________________________

由于比赛要求里最终得分标准是fmeasure而不是acc,故网上找来一段代码用以监测训练中查准率、查全率、fmeasure的变化。原地址找不到了,故而无法贴上,罪过罪过。

code

importkeras.backendasKdefprecision(y_true,y_pred):#Calculatestheprecisiontrue_positives=K.sum(K.round(K.clip(y_true*y_pred,0,1)))predicted_positives=K.sum(K.round(K.clip(y_pred,0,1)))precision=true_positives/(predicted_positives+K.epsilon())returnprecisiondefrecall(y_true,y_pred):#Calculatestherecalltrue_positives=K.sum(K.round(K.clip(y_true*y_pred,0,1)))possible_positives=K.sum(K.round(K.clip(y_true,0,1)))recall=true_positives/(possible_positives+K.epsilon())returnrecalldeffbeta_score(y_true,y_pred,beta=1):#CalculatestheFscore,theweightedharmonicmeanofprecisionandrecall.ifbeta< 0:        raise ValueError('The lowest choosable beta is zero (only precision).')    # If there are no true positives, fix the F score at 0 like sklearn.    if K.sum(K.round(K.clip(y_true, 0, 1))) == 0:        return 0    p = precision(y_true, y_pred)    r = recall(y_true, y_pred)    bb = beta ** 2    fbeta_score = (1 + bb) * (p * r) / (bb * p + r + K.epsilon())    return fbeta_scoredef fmeasure(y_true, y_pred):    # Calculates the f-measure, the harmonic mean of precision and recall.    return fbeta_score(y_true, y_pred, beta=1)

这里稍做图片增强,用Keras里的ImageDataGenerator函数,同时还可生成器方法进行训练。

code

fromkeras.preprocessing.imageimportImageDataGeneratortrain_datagen=ImageDataGenerator(width_shift_range=0.1,height_shift_range=0.1,zoom_range=0.1)val_datagen=ImageDataGenerator()#验证集不做图片增强batch_size=8train_generator=train_datagen.flow(X_train2,y_train2,batch_size=batch_size,shuffle=False)val_generator=val_datagen.flow(X_val,y_val,batch_size=batch_size,shuffle=False)

开始训练。这里在ModelCheckpoint里设置monitor监控feasure,mode为max,不再以最低loss作为模型最优的判断标准(个人做法,好坏可自行实验判断)。

code

checkpointer=ModelCheckpoint(filepath='weights_best_simple_model.hdf5',monitor='val_fmeasure',verbose=1,save_best_only=True,mode='max')reduce=ReduceLROnPlateau(monitor='val_fmeasure',factor=0.5,patience=2,verbose=1,min_delta=1e-4,mode='max')model.compile(optimizer='adam',loss='binary_crossentropy',metrics=['accuracy',fmeasure,recall,precision])epochs=20history=model.fit_generator(train_generator,validation_data=val_generator,epochs=epochs,callbacks=[checkpointer,reduce],verbose=1)

训练了20个epoch,这里给出第20个epoch时的训练结果,可以看到,val_loss 0.0233,其实已经挺低了;val_acc0.9945,参考意义不大(暂时不清楚有什么参考意义~~);val_fmeasure0.17,嗯。。任重道远啊。

训练了20个epoch,这里给出第20个epoch时的训练结果,可以看到,val_loss 0.0233,其实已经挺低了;val_acc0.9945,参考意义不大(暂时不清楚有什么参考意义~~);val_fmeasure0.17,嗯。。任重道远啊。

Epoch20/20500/500[==============================]-48s96ms/step-loss:0.0233-acc:0.9946-fmeasure:0.1699-recall:0.0970-precision:0.7108-val_loss:0.0233-val_acc:0.9946-val_fmeasure:0.1700-val_recall:0.0968-val_precision:0.7162 Epoch00020:val_fmeasuredidnotimprovefrom0.17148

以上只给出5000张图片的简单模型训练方法,但数据处理,搭建模型以及训练过程已经很清晰明了了,后面的进阶之路就凭大家各显身手了。

然后开始进行预测,导入测试集(当然是在训练集全部训练之后再进行测试集的预测)。

code

nub_test=len(glob('valid/*'))X_test=np.zeros((nub_test,224,224,3),dtype=np.uint8)path=[]i=0forimg_pathintqdm(glob('valid/*')):img=Image.open(img_path)ifimg.mode!='RGB':img=img.convert('RGB')img=img.resize((224,224))arr=np.asarray(img)X_test[i,:,:,:]=arri+=1100%|██████████████████████████████████████████████████████████████████████████████|8000/8000[02:18<00:00, 57.91it/s]

预测测试集并利用arr2tag函数将结果转为中文标签,以便生成提交文件。

code

y_pred=model.predict(X_test)y_tags=arr2tag(y_pred)

生成提交文件:

code

importosimg_name=os.listdir('valid/')img_name[:10]['000effcf2091ae3895074838b7e5f571186ab362.jpg', '0014455e5fbfd0961039fe23675debbb1a7b2308.jpg', '002138959ee7a14eb2860100392a384f8a85425f.jpg', '002414411ce17c6c7ab5d36dd3f956d0691ba495.jpg', '002780359fda7f09e6d1fc52d88aff90c6e8298b.jpg', '002ad24891ddf815bb86e4eca34415b1b44c9e4b.jpg', '002c284f94299bcee51733f7d6b17f3e4792d8c5.jpg', '002cf4b15887f32b688113a2a7a3f5786896d019.jpg', '003d4c12160b90fbbb2bd034ee30c251a45d9037.jpg', '0043ab4460cc79bfbea3db69d2a55d5f35600a37.jpg']

arr2tag函数得到的每张图片的标签是list格式,需转成str,在这里操作。经实验,windows中的方法与ubuntu中不同,后面也给出了ubuntu中本步的处理方法。

code

#windowsimportpandasaspddf=pd.DataFrame({'img_path':img_name,'tags':y_tags})foriinrange(df['tags'].shape[0]):df['tags'].iloc[i]=','.join(str(e)foreindf['tags'].iloc[i])df.to_csv('submit.csv',index=None)df.head()

code

##Ubuntuimportpandasaspddf=pd.DataFrame({'img_path':img_name,'tags':y_tags})foriinrange(df['tags'].shape[0]):df['tags'].iloc[i]=df['tags'].iloc[i][2:-2].replace(''',"").replace(''',"")df.to_csv('submit.csv',index=None)

整篇到此结束,有几点要说的:

提高方法。不用说,肯定是上预训练模型,可能再进行模型融合效果会更好。官方大大说整个标签由于人工标注,可能会跟机器预测出来的有别差,毕竟看预测结果中出现的 “一个人,人,仅一个女人,仅一个青年女人,仅女人,仅成年人” ,如果由人类来标注可能不会这么啰嗦~~所以可以考虑NLP方法对标签进行一些处理(我不会)。另外网上查到了个诡异的做法,说可以把fmeasure变成损失函数去训练模型(fmeasure不可导),我想如果有办法做到应该效果不错吧。

不足之处。训练过程中监控fmeasure和监控loss的做法,看上去应该是fmeasure没错,不过自己对于这块研究不够,只能凭感觉在做,各位看官可自由发挥。

整篇文章代码只有查准率、查全率、fmeasure部分为网上摘取,其他均为原创代码(略有借鉴),其实是想说,代码可能有些地方稚嫩,还望各位大佬们海涵。

如果想深入学习的话,我推荐还是报名实训营,让更有经验的大咖导师为你指路,效率和效果都会翻倍!

在这里推荐 CSDN 学院出品的《人工智能工程师直通车》实训营,目的是:通过 120 天的实战,将学员培养达到具备一年项目经验的人工智能工程师水平。CSDN 百天计划课程共分为 3 个阶段,4 个月完成。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 神经元
    +关注

    关注

    1

    文章

    363

    浏览量

    18400
  • ai技术
    +关注

    关注

    1

    文章

    1243

    浏览量

    23991

原文标题:没练过这个项目,怎么做AI工程师?

文章出处:【微信号:rgznai100,微信公众号:rgznai100】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    【先楫HPM5361EVK开发板试用体验】(原创)5.手把手实战AI机械臂

    嗨,亲爱的工程师、学生和爱好者们,我来啦!欢迎来到神秘的先楫半导体世界!如果您是一位电子工程师或者对魔法般的嵌入式技术感兴趣的话,那么来到的地方绝对没错!今天,我们将一起探索一个令人惊叹的先楫
    发表于 02-06 10:28

    手把手教你设计人工智能芯片及系统--(全阶设计教程+AI芯片FPGA实现+开发板)

    核心RTL代码、工具链代码、测试代码等;手把手教学:手把手教学员实现AI芯片设计,测试和实例应用,通过本课程的学习,将知晓AI芯片设计方法
    发表于 07-19 11:54

    【VIP福利六】300G人工智能资料,入门进阶AI技术

    手把手教你设计人工智能芯片及系统(全阶设计教程+AI芯片FPGA实现+开发板)详情链接:http://url.elecfans.com/u/c422a4bd15这里搜集了一批人工智能的学习资料,总共
    发表于 09-06 14:39

    AI的核心是什么?

    AI概念笼统,范围广大,到底什么才是AI的核心?手把手教你设计人工智能芯片及系统(全阶设计教程+AI芯片FPGA实现+开发板)详情链接:http://url.elecfans.com/
    发表于 10-18 06:39

    手把手教程:各类数字电源设计实例(程序+原理图)

    本资料分享了数字电源设计实例,包含程序、原理图等资料,手把手带你独立设计属于自己的数字电源。
    发表于 07-07 15:13

    手把手教你写批处理-批处理的介绍

    手把手教你写批处理-批处理的介绍
    发表于 10-25 15:02 69次下载

    美女手把手教你如何装机(中)

    美女手把手教你如何装机(中) 再来是硬碟的部份,这款机壳还不错,可以旋转支架~
    发表于 01-27 11:14 1420次阅读

    美女手把手教你如何装机(下)

    美女手把手教你如何装机(下) 接著下来就是今天的重头戏,开核萝!~
    发表于 01-27 11:16 2904次阅读

    手把手教你安装Quartus II

    本章手把手把地教你如何安装 Quartus II 软件 ,并将它激活 。此外 还有USB -Blaster下载器的驱动安装步骤 。
    发表于 09-18 14:55 9次下载

    手把手教你在家搭建监控系统

    手把手教你在家搭建监控系统
    发表于 01-17 19:47 24次下载

    手把手教你如何开始DSP编程

    手把手教你如何开始DSP编程。
    发表于 04-09 11:54 12次下载
    <b class='flag-5'>手把手</b>教你如何开始DSP编程

    手把手教你学LabVIEW视觉设计

    手把手教你学LabVIEW视觉设计手把手教你学LabVIEW视觉设计手把手教你学LabVIEW视觉设计手把手教你学LabVIEW视觉设计手把手
    发表于 03-06 01:41 2991次阅读

    手把手教你开关电源PCB排板

    手把手教你开关电源PCB排板(新型电源技术)-分享一下开关电源PCB排板的基本要点及分析,以及例子讲解。绝对的手把手
    发表于 09-18 12:27 57次下载
    <b class='flag-5'>手把手</b>教你开关电源PCB排板

    RT-Thread全球技术大会:QE工具移除AI技术壁垒与数据建立

    RT-Thread全球技术大会:QE工具移除AI技术壁垒与数据建立             审核编辑:彭静
    的头像 发表于 05-27 10:36 1406次阅读
    RT-Thread全球<b class='flag-5'>技术</b>大会:QE工具移除<b class='flag-5'>AI</b><b class='flag-5'>技术壁垒</b>与数据建立

    手把手教你学FPGA仿真

    电子发烧友网站提供《手把手教你学FPGA仿真.pdf》资料免费下载
    发表于 10-19 09:17 2次下载
    <b class='flag-5'>手把手</b>教你学FPGA仿真