新的知识点
对于多个非数值标签转化为数值label,产生字典
from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
le.fit(df['label'])
df['label'] = le.transform(df['label'])
label_map = dict(zip(le.classes_, le.transform(le.classes_)))
label_inv_map = {v: k for k, v in label_map.items()}
根据图片地址构建Dataset
任务中train_set与test_set中,图片以地址形式给出
使用cv2种的imread根据地址读入图片
其为BGR格式,转化为RGB
transform接受image,cv2读入数据后已经为ndarray类型,进行转换
import cv2
class My_dataset(Dataset):
def __init__(self, imgs_files, labels, transforms = None):
super(My_dataset, self).__init__()
self.imgs_files = imgs_files
self.labels = labels
self.transforms = transforms
def __getitem__(self, idx):
path = '/content'
imgs_path = os.path.join(path, self.imgs_files[idx])
image = cv2.imread(imgs_path)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
image = Image.fromarray(image)
if transforms is not None:
image = self.transforms(image)
label = self.labels[idx]
return image, label
def __len__(self):
return len(self.imgs_files)
遇到的一些问题和解决方案
如何查看经过transform之后的图片
def im_convert(tensor):
image = tensor.to("cpu").clone().detach()
image = image.numpy().squeeze()
image = image.transpose(1,2,0)
image = image.clip(0, 1)
return image
fig=plt.figure(figsize=(20, 12))
columns = 4
rows = 2
dataiter = iter(val_loader)
inputs, classes = dataiter.next()
for idx in range (columns*rows):
ax = fig.add_subplot(rows, columns, idx+1, xticks=[], yticks=[])
ax.set_title(num_to_class[int(classes[idx])])
plt.imshow(im_convert(inputs[idx]))
plt.show()
在训练集上准确率几乎为0
有可能是lr过大,开始时设置lr = 0.003,模型基本没有任何表达能力,在训练集上准确率几乎是0,后改为0.0003后有较好结果
模型不拟合,在训练集上准确率和验证集几乎相同,且都较低
这个开始时认为可能是超参数的问题,分别使用学习率为0.0001,0.00015,0.0002,0.0003和weight_decay为1e-3,1e-5进行训练,多次训练后发现lr=0.0001 & weight_decay = 1e-3有着最好的结果。但是在训练集和测试集上准确率在73%左右。
原因
在fc层,最后一层上加上了激活函数ReLU,导致了拟合速度变慢(具体为啥还没太清楚,猜测是因为加上激活函数后导致一些负分数没有了,损失函数在梯度下降的时候受到了影响,但改用softmax后结果变得更差)
猜想
loss function抽象的理解为评判真实标签和预测标签的差距的函数,loss的值理解为距离。按照线性回归问题来说,就是点之间的欧式距离,所以当使用ReLU函数的时候,会使得两点欧式距离拉近。使用softmax函数时候,因为都是小于0的数值,进行了softmax激活后,反而会导致更差的performance。
总结
踩了很多很简单的坑,还有一些问题没有解决,目前训练结束模型的score达到了0.85,就是baseline的水平,后续可以继续做data augmentation进行优化