李宏毅机器学习课后作业(hw3)

这部分作业需要安装pytorch,安装教程看主页或自行百度

直接上代码

import numpy as np
import pandas as pd
import os
import cv2
import torch
torch.cuda.is_available()

def readfile(path,label):
    img_dir = sorted(os.listdir(path))
    x = np.zeros((len(img_dir),128,128,3),dtype = np.uint8) # 图片存在这个维度
    y = np.zeros(len(img_dir),dtype = np.uint8) # 标签
    #z = []
    for i , file in enumerate(img_dir):
        x [i,:,:] = cv2.resize(cv2.imread(os.path.join(path,file)),(128,128))
        if label:
            y[i] = int(file.split('_')[0])
            #z.append(os.path.join(file))
    if label:
        return x, y
    else:
        return y
    
workspace_dir ='C:\\Users\\13554\\jupyter practice\\lihongyi\\hw3\\food-11'
print("Reading data")
train_x , train_y  = readfile(os.path.join(workspace_dir,"training"),True) #train_x.shape=9866,128,128,3;train_y.shape=9866,
print("Size of training data = {}".format(len(train_x)))
val_x , val_y = readfile(os.path.join(workspace_dir,"validation"),True)
print("Size of validation data = {}".format(len(val_x)))

import torchvision.transforms as transforms

train_transform = transforms.Compose([
    transforms.ToPILImage(),
    transforms.RandomHorizontalFlip(p=0.5), #水平翻转
    transforms.RandomVerticalFlip(p=0.5),#垂直翻转
    transforms.RandomRotation(degrees=(0,180)), # 随机旋转
    transforms.RandomPerspective(distortion_scale=0.3,p=0.5),
    transforms.ToTensor(),
    #transforms.Normalize(mean=(0.5,0.5,0.5),std=(0.5,0.5,0.5)),
])

test_transform = transforms.Compose([
    transforms.ToPILImage(),
    transforms.ToTensor(),
])

from torch.utils.data import DataLoader,Dataset
class ImgDataset(Dataset):
    def __init__(self,x,y=None,transform=None):
        self.x = x
        self.y = y
        if y is not None:
            self.y = torch.LongTensor(y)
        self.transform = transform
    def __len__(self):
        return len(self.x)
    def __getitem__(self,index):
        X = self.x[index]
        if self.transform is not None:
            X = self.transform(X)
        if self.y is not None:
            Y = self.y[index]
            return X,Y
        else:
            return X
           
batch_size = 64
train_set = ImgDataset(train_x,train_y,train_transform) # 实例化train_set
val_set = ImgDataset(val_x,val_y,test_transform)
train_loader = DataLoader(train_set,batch_size = batch_size,shuffle = True)
val_loader = DataLoader(val_set,batch_size = batch_size ,shuffle=False)

import torch.nn as nn
class Classifier(nn.Module):
    def __init__(self):
        super(Classifier,self).__init__()
        self.cnn = nn.Sequential(
            nn.Conv2d(3,64,3,1,1), #[64,128]
            nn.BatchNorm2d(64),
            nn.ReLU(),
            nn.MaxPool2d(2,2,0), 
            
            nn.Conv2d(64,128,3,1,1), # [128,64]
            nn.BatchNorm2d(128),
            nn.ReLU(),
            nn.MaxPool2d(2,2,0),
            
            nn.Conv2d(128, 256, 3, 1, 1), # [256, 32]
            nn.BatchNorm2d(256),
            nn.ReLU(),
            nn.MaxPool2d(2, 2, 0),      

            nn.Conv2d(256, 512, 3, 1, 1), # [512, 16]
            nn.BatchNorm2d(512),
            nn.ReLU(),
            nn.MaxPool2d(2, 2, 0),       
            
            nn.Conv2d(512, 512, 3, 1, 1), # [1024, 8]
            nn.BatchNorm2d(512),
            nn.ReLU(),
            nn.MaxPool2d(2, 2, 0),       
            
        )
        self.fc = nn.Sequential(
            nn.Linear(512*4*4,1024),
            nn.ReLU(),
            nn.Linear(1024,512),
            nn.ReLU(),
            nn.Linear(512,11)
        )
    def forward(self,x):
        out = self.cnn(x)
        out = out.view(out.size()[0],-1)
        return self.fc(out)

model  = Classifier().cuda()  # 模型也要转成cuda
loss = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(),lr = 0.001,betas=(0.9,0.999),eps=1e-8,weight_decay=0.0005) #momentum = 0.9,,betas=(0.9,0.999),eps=1e-8,weight_decay = 0.001
num_epoch = 300
val_bestacc=0
train_bestacc=0
for epoch in range(num_epoch):
#epoch_stat_time = time.time()
    train_acc = 0.0
    train_loss = 0.0
    val_acc = 0.0
    val_loss = 0.0
    model.train()
    for i,data in enumerate(train_loader):
        optimizer.zero_grad()
        train_pred = model(data[0].cuda())
        #print(train_pred.shape)
        batch_loss = loss(train_pred,data[1].cuda() )
        batch_loss.backward() #反向传播,计算当前梯度
        optimizer.step() #更新参数
        # 最大值的索引:
        train_acc += np.sum(np.argmax(train_pred.cpu().data.numpy(),axis = 1) == data[1].numpy())
        train_loss += batch_loss.item()
        
    model.eval()
    with torch.no_grad():
        for i,data in enumerate(val_loader):
            val_pred = model(data[0].cuda()) # 验证集的pred
            batch_loss = loss(val_pred,data[1].cuda())
            val_acc += np.sum(np.argmax(val_pred.cpu().data.numpy(),axis = 1) == data[1].numpy())
            val_loss += batch_loss.item()
    print('[%03d/%03d]  Train Acc: %3.6f Loss: %3.6f | Val Acc: %3.6f loss: %3.6f' % \
            (epoch + 1, num_epoch, train_acc/train_set.__len__(), train_loss/train_set.__len__(), val_acc/val_set.__len__(), val_loss/val_set.__len__()))
    if(val_acc>val_bestacc):
        val_bestacc=val_acc
    if(train_acc>train_bestacc):
        train_bestacc=train_acc
    print('train_bestacc: %3.6f  | val_bestacc: %3.6f'%(train_bestacc/train_set.__len__(),val_bestacc/val_set.__len__()))

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