otto-group-product-classification-challenge(Pytorch處理多分類問題)


參考一:《Pytorch深度學習實踐》(第九集)

參考二:Otto-Neural-Net

注意:使用的數據來自kaggle,鏈接

由於上面給出的兩個參考鏈接,對代碼的講解都已經很詳細,所以這里不再贅述,下面按自己的理解整理了代碼如下:

Imports

import numpy as np
import pandas as pd
import os
import time
from xgboost import XGBClassifier
import matplotlib.pyplot as plt
import torch
from torch.utils.data import Dataset, DataLoader
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim

Prepare Data

# 處理數據
csv_path = os.path.join('train.csv')
datas = pd.read_csv(csv_path)
datas = datas.copy() 
datas = datas.drop(columns='id')
datas = datas.sample(frac=1)

# 將category轉化為數字
datas.target = datas.target.astype('category').cat.codes
# 划分數據集
rows, _ = datas.shape  # type(datas) 為 <class 'pandas.core.frame.DataFrame'>
train_rows = int(rows*0.7)
train_datas = datas.iloc[:train_rows, :]
val_datas = datas.iloc[train_rows:, :]

# 得到features和targets
train_features = train_datas.loc[:, train_datas.columns!='target'].values  # values 得到一個矩陣
train_targets = train_datas.target.values

val_features = val_datas.loc[:, val_datas.columns!='target'].values
val_targets = val_datas.target.values
# 封裝 繼承dataset
class CustomDataset(Dataset):
    def __init__(self, features, targets):
        super(CustomDataset, self).__init__()
        
        self.features = features
        self.targets = targets
    
    def __len__(self):
        return len(self.features)
    
    def __getitem__(self, idx):
        return self.features[idx], self.targets[idx]


# 得到Dataset類
train_ds = CustomDataset(train_features, train_targets)
val_ds = CustomDataset(val_features, val_targets)

# 得到DataLoader
batch_size = 64
train_loader = DataLoader(train_ds, batch_size=batch_size)
val_loader = DataLoader(val_ds, batch_size=batch_size)

Device

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

Design Model

class Net(torch.nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        
        self.l1 = torch.nn.Linear(93, 64)
        self.bn = torch.nn.BatchNorm1d(num_features=64)
        self.l2 = torch.nn.Linear(64, 32)
        self.dropout = torch.nn.Dropout(p=0.1)
        self.l3 = torch.nn.Linear(32, 16)
        self.l4 = torch.nn.Linear(16, 9)
    
    def forward(self, x):
        # first layer
        x = self.l1(x)
        x = self.bn(x)
        x = torch.relu(x)
        # second layer
        x = self.l2(x)
        x = self.dropout(x)
        x = torch.relu(x)
        
        x = torch.relu(self.l3(x))
        return self.l4(x)  # 注意 這里不要加relu

model = Net().to(device)

Construct Loss and Optimizer

criterion = torch.nn.CrossEntropyLoss().to(device)
optimizer = torch.optim.SGD(model.parameters(), lr=0.01, momentum=0.5)

Train and Validate

def train():
    losses = 0.0
    accs = 0.0
    for idx, data in enumerate(train_loader, 0):
        inputs, targets = data
        inputs = inputs.to(device)
        targets = targets.to(device)
        optimizer.zero_grad()
        
        # forward + backward + update
        outputs = model(inputs.float())
        loss = criterion(outputs, targets.long())
        loss.backward()
        optimizer.step()
        
        losses += loss.item()
        _, predicted = torch.max(outputs.data, dim=1)
        accs += (predicted==targets).sum().item()
        
    losses /= len(train_loader)
    accs = accs * 100 / len(train_ds)
    print('Training:  loss: %.2f    accuracy: %.2f %%' %(losses, accs))
    
    return losses, accs
def val():
    losses = 0.0
    accs = 0.0
    with torch.no_grad():
        for data in val_loader:
            inputs, labels = data
            inputs = inputs.to(device)
            labels = labels.to(device)
            outputs = model(inputs.float())
            losses += criterion(outputs, labels.long()).item()
            _, predicted = torch.max(outputs.data, dim=1)
            accs += (predicted == labels).sum().item()
    losses /= len(val_loader)
    accs = accs * 100 / len(val_ds)
    print('Validating:   loss: %.2f    accuracy: %.2f %%' %(losses, accs))
    
    return losses, accs
train_losses = []
val_losses = []
train_accs = []
val_accs = []
maxAcc = 0  # 記錄最高准確率

for epoch in range(100):
    print('[epoch: %d]' % (epoch+1))
    
    losses, accs = train()
    train_losses.append(losses)
    train_accs.append(accs)
    
    losses, accs = val()
    val_losses.append(losses)
    val_accs.append(accs)
    
    if maxAcc < accs:
        maxAcc = accs
    
    check = np.greater(maxAcc, val_accs[-5:])
    if (check.all()==True)  and (epoch>20):
        print('Convergence met!\n')
        break

print('Maximum validation accuracy: %.2f %%' % (maxAcc))

Plot Losses

# 這里采用了指數平滑
import math
import matplotlib.pyplot as plt

tmp_train_losses = [math.e**i for i in train_losses]
tmp_val_losses = [math.e**i for i in val_losses]
plt.figure(figsize=(10, 5))
plt.plot(tmp_train_losses, 'r', label='Training')
plt.plot(tmp_val_losses, 'b', label='Validating')
plt.xlabel('Epoch')
plt.ylabel('Loss per epoch')
plt.legend()
plt.show()


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM