Machine Learning Homework 3 - Image Sentiment Classification Kaggle题解报告(基于pytorch架构)

 

题目:

我們提供給各位的training dataset為兩萬八千張左右48x48 pixel的圖片,以及每一張圖片的表情label(注意:每張圖片都會唯一屬於一種表情)。總共有七種可能的表情(0:生氣, 1:厭惡, 2:恐懼, 3:高興, 4:難過, 5:驚訝, 6:中立(難以區分為前六種的表情))。

Testing data則是七千張左右48x48的圖片,希望各位同學能利用training dataset訓練一個CNN model,預測出每張圖片的表情label(同樣地,為0~6中的某一個)並存在csv檔中。

分析:

1.首先根据train.csv构造自己的数据集

          由于每张图片的feature位于一个单元格中,所以首先要用spilt()把数字字符串数据转换成48*48大小的数值型列表,此时要注意数值类型必须为float类型

import pandas as pd
data=pd.read_csv(‘data/train.csv’)
image=data.iloc[idx,1].split()
image=list(map(float,image))
image=np.array(image).reshape(-1,48)

image有了,接下来就是存储lable了,lable是0-6的int型整数.

lable=np.array(self.data.iloc[idx,0])

所以CNN的输出层必然为7层,输入层只有1个channel.

数据准备完毕,便要继承Dataset实现自己的数据集类,使得pytorch能够自动对数据集batch,shuffle,transform等操作,不需要自己写代码完成这些功能

class ISCDataset(Dataset):
    def __init__(self,csv_file,transform=None):
        self.data=pd.read_csv(csv_file)
        self.transform=transform

    def __len__(self):
        return len(self.data)

    def __getitem__(self, idx):
        image=self.data.iloc[idx,1].split()
        image=list(map(float,image))
        image=np.array(image).reshape(-1,48)
        lable=np.array(self.data.iloc[idx,0])

        sample={'image':image,'lable':lable}
        if self.transform:
            sample = self.transform(sample)

        return sample

2.构造自己的CNN网络

这一部分,仁者见仁智者见智,不同的人设计的层数,参数各有不同,只要网络结构不报错,剩下的便是调参了。值得一提的是,刚开始我的lr设的比较大,结果就是所有图片的预测结果都一样,后来print每次的预测情况才发现----执行几次batch之后,预测结果便不在是数字了,变成了nan或inf,这显然是因为预测值太大造成的,所以就要把lr设的足够小才行。另外由于分类个数(7类)比较多,刚开始正确率很低是极其正常的,让它多循环几次准确率就会不断上升。

class ConvNet(torch.nn.Module):
    def __init__(self):
        super(ConvNet, self).__init__()
        self.conv1=torch.nn.Conv2d(1,6,3,1)
        self.pooling1=torch.nn.MaxPool2d(2)
        self.conv2=torch.nn.Conv2d(6,1,3,1)
        self.fc1=torch.nn.Linear(21*21,100)
        self.fc2=torch.nn.Linear(100,10)
        self.fc3=torch.nn.Linear(10,10)
        self.fc4=torch.nn.Linear(10,7)

    def forward(self, x):
        x=F.relu(self.conv1(x.float()))
        x=self.pooling1(x)
        x=F.relu(self.conv2(x))
        x=x.view(-1,1*21*21)
        x=F.relu(self.fc1(x))
        x=F.relu(self.fc2(x))
        x=F.relu(self.fc3(x))
        x=self.fc4(x)
        #x=F.softmax(x)
        return x

另外:由于原始数据未提供测试集,所以要从训练集中选择一部分做验证集,注意这一部分不是在构造数据集时做的,而是在跑模型时,令某几个batch不再更新参数变为验证集,然后对这部分测试正确率。这样做的好处是验证集都是shuffle=True来的,也就很随机,可信度更高。

if i_batch<=6000:
           
            prediction=net(item['image'])
   
            loss=loss_fn(prediction,item['lable'])

            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
else:
            #print(len(item['lable']))
            with torch.no_grad():
                num_verificationData+=len(item['lable'])
                veri_prediction=net(item['image'])
                
                veri_prediction=torch.argmax(veri_prediction,dim=1).numpy()
               
                for j in range(len(item['lable'])):
                    if veri_prediction[j]==item['lable'].numpy()[j]:
                        num_right+=1
                

3.保存对test.csv的测试结果到sample.csv

通过分析两个csv文件发现,只需要按顺序(所以加载test.csv时shuffle值必须为False)把test.csv预测结果按顺序写到sample.csv中即可(即更新csv中的某个cell)

#读入test.csv
test_dataset=ISCDataset('data/test.csv',transform=transforms.Compose([ToTensor()]))
testloader=DataLoader(test_dataset,batch_size=4,shuffle=False)
 #读入sample.csv
sample=pd.read_csv('data/sample.csv')
for i_batch,item in enumerate(testloader):
    prediction=net(item['image'])
    prediction=torch.argmax(prediction,dim=1).numpy()
    for i in range(len(prediction)):
        sample.iloc[item['lable'].numpy()[i],1]=prediction[i]
#sample.iloc[0,1]=10
#print(sample,type(sample))
sample.to_csv('data/sample.csv',index=False)

4.整个项目代码

可运行完整代码已放到github上,欢迎大家fork,star,watch甚至issue

https://github.com/zc-authorization/Image_Sentiment_Classification

另:     有问题大家可以在下面评论,看到都会回复

猜你喜欢

转载自blog.csdn.net/baidu_20965275/article/details/83473173
今日推荐