PyTorch解决多分类问题

PyTorch解决多分类问题

softmax函数

糖尿病数据集分类为0和1,MNIST数据集中有10个分类。

神经网络希望输出之前带有竞争性的结果,即所有概率之和为1,且所有概率均大于0,使用softmax可以实现这两个特点。
softmax函数
$p(y = i) = \frac{e^{Z_i}}{\Sigma_{j=0}^{K-1}e^{Z_j}},i\in \{0,…,K-1\}$

CrossEntropyLoss vs NLLLoss

NLLLOSS 损失函数
负对数似然损失

1
2
3
4
5
6
7
8
9
10
11
# -*- coding: UTF-8 -*-
import numpy as np

y = np.array([1,0,0])
z = np.array([0.2,0.1,-0.1])

y_pred = np.exp(z) / np.exp(z).sum()
print(y_pred)

loss = (-y * np.log(y_pred)).sum()
print(loss)

CrossEntropyLoss 损失函数
CrossEntropyLoss 损失函数 = Softmax + NLLLoss损失函数

1
2
3
4
5
6
7
8
# -*- coding: UTF-8 -*-
import torch

y = torch.LongTensor([0,1])
z = torch.Tensor([[0.3,0.1,-0.1],[0.1,1,-0.1]])
loss_fuction = torch.nn.CrossEntropyLoss()
loss = loss_fuction(z,y)
print(loss.item())

MINIST数据集

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
import sys

import torch
import torch.nn as nn
import torch.optim as optim

from tqdm import tqdm

from torchvision import transforms
from torchvision import datasets
from torch.utils.data import DataLoader

from model import Net

transform = transforms.Compose([
# 将像素转化为张量
transforms.ToTensor(),
# 均值 标准差 -> 归一化为0-1正态分布
transforms.Normalize((0.1307,),(0.3081))
])

batch_size = 512

train_dataset = datasets.MNIST(root='./dataset/',train=True,download=False,transform=transform)

train_loader = DataLoader(train_dataset,shuffle=True,batch_size=batch_size)

test_dataset = datasets.MNIST(root='./dataset/',train=False,download=False,transform=transform)

test_loader = DataLoader(test_dataset,shuffle=False,batch_size=batch_size)

model = Net()
loss_function = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(),lr=0.01)

epoches = 1000
test_num = len(test_dataset)
train_steps = len(train_loader)
for epoch in range(epoches):
model.train()
running_loss = 0.0
train_bar = tqdm(train_loader,file=sys.stdout)
for step,data in enumerate(train_bar):
inputs,targets = data

optimizer.zero_grad()
outputs = model(inputs)
loss = loss_function(outputs,targets)
loss.backward()
optimizer.step()

running_loss += loss.item()

train_bar.desc = 'train epoch[{}/{}] loss:{:.3f}'.format(epoch + 1,epoches,loss.item())

model.eval()
acc = 0.0
with torch.no_grad():
test_bar = tqdm(test_loader,file=sys.stdout)
for test_datas in test_bar:
test_inputs,test_targets = test_datas
test_outputs = model(test_inputs)
# _,predict_y = torch.max(test_outputs,dim=1)
predict_y = torch.max(test_outputs,dim=1)[1]
acc += torch.eq(predict_y,test_targets).sum().item()
val_acc = acc / test_num
print('[epoch %d] train_loss: %.3f val_acc: %.3f' % (epoch + 1,running_loss / train_steps, val_acc))

Kaggle — Otto Group Product Classification Challenge

Otto Group Product Classification Challenge

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import torch.nn as nn
import torch.nn.functional as F

class Net(nn.Module):
def __init__(self):
super(Net,self).__init__()
self.l1 = nn.Linear(93,128)
self.l2 = nn.Linear(128,256)
self.l3 = nn.Linear(256,512)
self.l4 = nn.Linear(512,256)
self.l5 = nn.Linear(256,128)
self.l6 = nn.Linear(128,64)
self.l7 = nn.Linear(64,32)
self.l8 = nn.Linear(32,9)

def forward(self,x):
x = F.relu(self.l1(x))
x = F.relu(self.l2(x))
x = F.relu(self.l3(x))
x = F.relu(self.l4(x))
x = F.relu(self.l5(x))
x = F.relu(self.l6(x))
x = F.relu(self.l7(x))

return self.l8(x)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import random
import csv

def split_dataset(input_file,train_output_file,val_output_file,split_ratio=0.9):
with open(input_file,'r',newline='') as csvfile:
reader = csv.reader(csvfile)
header = next(reader) # Assuming the first row is the header
data = list(reader)

random.shuffle(data) # Shuffle the data randomly

split_index = int(len(data) * split_ratio)

train_data = data[:split_index]
val_data = data[split_index:]

with open(train_output_file,'w',newline='') as train_csv:
train_writer = csv.writer(train_csv)
train_writer.writerow(header)
train_writer.writerows(train_data)

with open(val_output_file,'w',newline='') as val_csv:
val_writer = csv.writer(val_csv)
val_writer.writerow(header)
val_writer.writerows(val_data)

input_file = './dataset/train.csv' # 输入CSV文件名
train_output_file = './dataset/train_new.csv' # 训练集输出文件名
val_output_file = './dataset/val_new.csv' # 测试集输出文件名
split_ratio = 0.9 # 切分比例

split_dataset(input_file, train_output_file, val_output_file, split_ratio)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
import os
import sys
import numpy as np
import pandas as pd
from tqdm import tqdm

import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import Dataset
from torch.utils.data import DataLoader

from model import Net


class OttoDataset(Dataset):
def __init__(self,filepath):
datasets = pd.read_csv(filepath)
labels = datasets['target']

self.len = datasets.shape[0]
self.x_datas = torch.tensor(np.array(datasets)[:,1:-1].astype(float))
self.y_datas = self.labels2id(labels)

def __getitem__(self,index):
return self.x_datas[index],self.y_datas[index]

def __len__(self):
return self.len

def labels2id(self,labels):
target_id = []
target_labels = ['Class_1','Class_2','Class_3','Class_4','Class_5','Class_6','Class_7','Class_8','Class_9']
for label in labels:
target_id.append(target_labels.index(label))

return target_id

train_dataset = OttoDataset('./dataset/train_new.csv')
val_dataset = OttoDataset('./dataset/val_new.csv')

train_loader = DataLoader(dataset=train_dataset,batch_size=128,shuffle=True,num_workers=0)
val_loader = DataLoader(dataset=val_dataset,batch_size=128,shuffle=False,num_workers=0)

model = Net()
loss_function = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(),lr=0.001)

epoches = 1000
val_num = len(val_dataset)
train_steps = len(train_loader)
for epoch in range(epoches):
model.train()
running_loss = 0.0
train_bar = tqdm(train_loader,file=sys.stdout)

for step,datas in enumerate(train_bar):
inputs,targets = datas

optimizer.zero_grad()
outputs = model(inputs.float())
loss = loss_function(outputs,targets)
loss.backward()
optimizer.step()

running_loss += loss.item()

train_bar.desc = 'train epoch[{}/{}] loss:{:.3f}'.format(epoch + 1,epoches,loss.item())

model.eval()
acc = 0.0
with torch.no_grad():
val_bar = tqdm(val_loader,file=sys.stdout)

for val_datas in val_bar:
val_inputs,val_targets = val_datas
val_outputs = model(val_inputs.float())

predict = torch.max(val_outputs,dim=1)[1]
acc += torch.eq(predict,val_targets).sum().item()
val_acc = acc / val_num
print('[epoch %d] train_loss: %.3f val_acc: %.3f' % (epoch + 1,running_loss / train_steps,val_acc))
Donate comment here