多标签图像分类竞赛地址:https://www.tinymind.cn/competitions/42?from=blog
队伍:for the dream,其实是大酒神死忠粉~
初次拿到这个题目,想了想做过了猫狗大战这样的二分类,也做过cifar-10这样的多分类,类似本次比赛的题目多标签图像分类的确没有尝试过。6941个标签,每张图片可能没有标签也可能存在6941个标签,即各个标签之间是不存在互斥关系的,所以最终分类的损失函数不能用softmax而必须要用sigmoid。然后把分类层预测6941个神经元,每个神经元用sigmoid函数返回是否存在某个标签即可。
来蹚下整个流程看看,在jupyter notebook上做得比较乱,但是整个流程还是可以看出来的。深度学习模型用的Keras。
先导入train_csv数据,这里用的是最初版的训练csv文件,img_path里存在地址,后面做了处理。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
from glob import glob
from tqdm import tqdm
import cv2
from PIL import Image
train_path = 'visual_china_train.csv'
train_df = pd.read_csv(train_path)
train_df.head()
train_df.shape
#(35000, 2)
可以看到总共有35000张训练图片,第一列为图片名称(带地址,需处理),第二列为图片对应标签。
来看下是不是的确只有6941个标签:
tags = []
for i in range(train_df['tags'].shape[0]):
for tag in train_df['tags'].iloc[i].split(','):
tags.append(tag)
tags = set(tags)
len(tags)
#6941
事实证明标签总数无误,可以放心大胆地继续进行下去了。
然后我处理了下图片名称,并存到了img_paths列表里。
#如果使用的是官方后来更新的visual_china_train.csv,可以直接使用最后一行代码
for i in range(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转变成对应的中文标签。(实际上最后还需要做下处理)
def hash_tag(filepath):
fo = open(filepath, "r",encoding='utf-8')
hash_tag = {}
i = 0
for line in fo.readlines(): #依次读取每行
line = line.strip() #去掉每行头尾空白
hash_tag[i] = line
i += 1
return hash_tag
def load_ytrain(filepath):
y_train = np.load(filepath)
y_train = y_train['tag_train']
return y_train
def arr2tag(arr):
tags = []
for i in range(arr.shape[0]):
tag = []
index = np.where(arr[i] > 0.5)
index = index[0].tolist()
tag = [hash_tag[j] for j in index]
tags.append(tag)
return tags
读入valid_tags.txt,并生成索引和标签的映射。
filepath = "valid_tags.txt"
hash_tag = hash_tag(filepath)
hash_tag[1]
#'0到1个月'
载入y_train
y_train = load_ytrain('tag_train.npz')
y_train.shape
#(35000, 6941)
前期准备工作差不多做完了,开始导入训练集。此处有个坑,即原始训练集中存在CMYK格式的图片,传统图片处理一般为RGB格式,所以使用Image库中的convert函数对非RGB格式的图片进行转换。
nub_train = 5000 #可修改,前期尝试少量数据验证模型
X_train = np.zeros((nub_train,224,224,3),dt