阿里云天池 - 2018之江杯全球人工智能大赛 之零样本图像目标识别 参赛总结

    9月份报名做了 2018之江杯全球人工智能大赛 之零样本图像目标识别 的这道题 -     题目链接-https://tianchi.aliyun.com/competition/entrance/231677/introduction
    初赛中获得了135名(共3224支队伍参赛),虽没有进入前100名进入决赛,也勉强算是top %5吧。


    在此总结一下比赛的收获:
   

    自四月底完成了12306图片验证码的破解以后的几个月,陆续研究了RNN/Yolo之类的算法,
    才发现深度学习实在内容太多,多年不学习,要赶上潮流很困难。。
    
    一个偶然的机会发现了阿里云天池 - 2018之江杯全球人工智能大赛 之零样本图像目标识别 的比赛,
    刚开始啥叫零样本目标识别都不知道,以为就是普通的图片分类,于是报名。
    因为没太理解题目,直接做了个图像分类,提交测试,发现完全不行。于是仔细研究了一下 零样本图像目标识别,重新开始调整算法。
    
    那么图像分类和零样本目标识别有啥不同??
    图像分类 - 拿12306火车票图片来说吧,总共80种,比如其中一类为红枣,给你100个红枣的图片,尽管这100个红枣的图片千差万别,但都是红枣,机器就拿这100个样本学习并记住其
    特征,比如红色的、椭圆的,表皮有褶皱的等等。    同样,对于另外79种,也一样操作,学习完成了,你给一张图片,给机器识别,机器提取该张图片的特征后,在学习过的80种中间挑出机器认为概率最大的一个。-------  注意,图片分类,机器识别的结果只能是
    机器学习过的80种图片中间的一种,如果你给一个80种图片以外的其他图片,机器是无法识别出来的。
    
    零样本图像目标识别 - 与图像分类不同,比如,给你一类猪的图片,100张各种各样的猪,机器学习完成以后,需提取猪的各种特征,如四条腿、大耳朵、2只眼睛,鼻孔很大等等。学习完成以后呢,
    给机器一张牛的图片识别,需要机器认出来这是一头牛 ---  注意:牛这个类别机器以前的学习样本中是没有牛这个类别的。这才是本质的区别!!!!!
    
    图像分类算法很简单,就不用提了,那这个零样本目标识别算法咋整???
    零样本图像目标识别的基本思路:
    1. 与图片分类已有,对已有样本类别用深度学习模型提取 图片特征
    2. 对已有图片文字类别名称矢量化 - word2Vec  ---   比赛题目中,出题方已经帮大家完成了矢量化的操作,不用自己单独提取。-- 注意,这个矢量化包括学习样本以外的其他类别,如牛这个类别
    3. 对以后图片的各个类别做特征标注 - 比赛题目中,出题方已经帮大家完成了各个类别的标注,不用自己手工标注。 ---  注意,这个标注包括学习样本以外的其他类别,如牛这个类别
    4. 将每类图片提取出来的特种映射到 类别名称矢量 或 类别特征标注,使得该图片与对应的矢量或特征标注某种距离最小。
    5. 完成学习以后,当输入一张新的图片时,深度学习提取图片特征做矢量映射, 
       然后计算该矢量与 步骤3或4 的所有类别(包括学习样本的类别以及学习样本以外的类别)的距离,取距离最小的那个类别为识别目标。
       
    在实际比赛中,发现用图片特征标注计算距离效果很差,实际我只用到了word2Vec矢量。
    
    因比赛方提供的数据已经做好了很多准备工作,所以数据预处理工作量不大,参赛者只需实现核心代码,算法代码部分非常简短。
    
    1. 图片特征提取用了残差网络ResNet。
    2. 代码用最简单的keras实现
    3. 只用了类别矢量化,没用手工标注数据。
    4. 预赛二阶段的数据准确率还不到10%,与前排的大神差距非常大。-- 前排大神 都是20%多。
    5. 训练时用了数据扩增 data augument,划分了10%的验证集,避免过拟合,使用了checkpoint/early_stop,和动态调整学习率。
       算法的非核心代码不值一提,算法的training部分的核心代码非常少,如下所示。供各位有兴趣的同学学习参考。

def res_embed_train_cnn(input_train_pkl,val_data_pkl,class_embed_pkl,output_pkl,bst_model_path):

   pkl_file = open(class_embed_pkl, 'rb')
   class_embed_mat = pickle.load(pkl_file)
   pkl_file.close()

   num_feature=class_embed_mat.shape[1]

   batch_size = 512
   num_class=285
   epochs = 300
   img_rows, img_cols = 64,64

   x, train_y_int = read_training_data_dir(input_train_pkl)
   val_x, val_y_int = read_training_data(val_data_pkl)

   if K.image_data_format() == 'channels_first':
       input_shape = (3, img_rows, img_cols)
       input_shape_pics=(len(train_y_int),3, img_rows, img_cols)
       val_shape_pics=(len(val_y_int),3, img_rows, img_cols)
   else:
       input_shape = (img_rows, img_cols, 3)
       input_shape_pics=(len(train_y_int),img_rows, img_cols,3)
       val_shape_pics=(len(val_y_int),img_rows, img_cols,3)
  
   train_x=x.reshape(input_shape_pics)
   val_x=val_x.reshape(val_shape_pics)
   train_y=to_categorical(train_y_int, num_classes=num_class)
   val_train_y=to_categorical(val_y_int, num_classes=num_class)

#for debug only
   #train_x=train_x[0:256]
   #val_x=val_x[0:256]
   #train_y=train_y[0:256]
   #val_train_y=val_train_y[0:256]
#debug end

   print("begin cnn training ...")
   
   X_input = Input(shape=input_shape)
  
    # Stage 1  
   X = Conv2D(64,kernel_size=(3,3),strides=(1,1),name="conv1",padding='same',kernel_initializer=glorot_uniform(seed=0))(X_input)  
   X = BatchNormalization(axis=3,name="bn_conv1")(X)  
   X = Activation("relu")(X)  
   #X = MaxPooling2D(pool_size=(2,2),padding='same',strides=(1,1))(X)
   X = MaxPooling2D(pool_size=(2,2),strides=(2,2))(X)  
  
    # Stage 2  
   X = convolutional_block(X,f=3,filters=[64,64,128],stage=2,block="a",s=2,d=0.25)  
   X = identity_block(X,f=3,filters=[64,64,128],stage=2,block="b")  
   X = identity_block(X,f=3,filters=[64,64,128],stage=2,block="c")  
  
    #Stage 3  
   X = convolutional_block(X,f=3,filters=[128,128,256],stage=3,block="a",s=2,d=0.25)  
   X = identity_block(X,f=3,filters=[128,128,256],stage=3,block="b")  
   X = identity_block(X,f=3,filters=[128,128,256],stage=3,block="c")  
   X = identity_block(X,f=3,filters=[128,128,256],stage=3,block="d")  
  
    # Stage 4  
   X = convolutional_block(X,f=3,filters=[256,256,512],stage=4,block="a",s=2,d=0.5)
   #X = Dropout(0.25)(X)
   X = identity_block(X,f=3,filters=[256,256,512],stage=4,block="b")  
   X = identity_block(X,f=3,filters=[256,256,512],stage=4,block="c")  
   X = identity_block(X,f=3,filters=[256,256,512],stage=4,block="d")  
   X = identity_block(X,f=3,filters=[256,256,512],stage=4,block="e")  
   X = identity_block(X,f=3,filters=[256,256,512],stage=4,block="f")  
  
    #Stage 5  
   X = convolutional_block(X,f=3,filters=[512,512,1024],stage=5,block="a",s=2,d=0.5)
   X = identity_block(X,f=3,filters=[512,512,1024],stage=5,block="b")  
   X = identity_block(X,f=3,filters=[512,512,1024],stage=5,block="c")  
  
    #最后阶段  
    #平均池化  
   X = AveragePooling2D(pool_size=(2,2))(X)  
  
    #输出层  
   X = Flatten()(X)    #展平
   X = Dropout(0.5)(X)
   X = Dense(num_feature)(X)
   X = LeakyReLU()(X)

   X=Dense(num_class, activation='softmax', trainable=False, kernel_initializer=custom_kernel_init_embed)(X)
 
   model = Model(X_input, X)
   model.compile(loss='categorical_crossentropy', optimizer='adam',metrics=['categorical_accuracy'])  
   model.summary()   

   #print("reading train_model data...")
   #model.load_weights(output_pkl+'_weights')                  #for continue training

   reduce_lr=ReduceLROnPlateau(monitor='loss', factor=0.1, patience=5, verbose=1, mode='min', min_delta=0.0001, cooldown=10, min_lr=0)
   model_checkpoint = ModelCheckpoint(bst_model_path, verbose=1,save_best_only=True,monitor='val_loss',mode='min')
   early_stopping=EarlyStopping(monitor='loss',patience=80,verbose=1,mode='min')
   
#augermentation training
   #train_datagen = ImageDataGenerator(rotation_range=30,zoom_range=0.2,channel_shift_range=10,width_shift_range=0.15,shear_range=0.1,
                                      height_shift_range=0.15,horizontal_flip=True,vertical_flip=True)
   train_datagen = ImageDataGenerator( rotation_range=15,width_shift_range=0.15,height_shift_range=0.15,horizontal_flip=True,vertical_flip=True)
   #train_datagen = ImageDataGenerator( rotation_range=15,width_shift_range=5,height_shift_range=5,horizontal_flip=True,vertical_flip=True)
   train_datagen.fit(train_x)
   model.fit_generator(train_datagen.flow(train_x,train_y, batch_size=batch_size),steps_per_epoch=len(train_x)/batch_size,
                       epochs=epochs,verbose=1,validation_data=(val_x,val_train_y),callbacks=[model_checkpoint,early_stopping,reduce_lr])

   model.save(output_pkl)                      #save model,for predict
   model.save_weights(output_pkl+'_weights')   #save weights,for continue training
   
   print('Training over!')

   return

 

你可能感兴趣的:(深度学习,机器学习)