pytorch-多分类问题

一、softmax

softmax计算公式:

交叉熵损失函数:(p(i)真实分布,q(i)预测)

相对熵(KL散度):

交叉熵损失与nll损失

eg.numpy:

1
2
3
4
5
6
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()
loss = (- y*np.log(y_pred)).sum()
print(loss)

pytorch:

1
2
3
4
5
6
import torch
y = torch.LongTensor([0])
z = torch.Tensor([0.2,0.1,-0.1])
criterion = torch.nn.CrossEntropyLoss()
loss = criterion(z,y)
print(loss)

二、miniset数据集分类(带可视化)

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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import torch
from torchvision import transforms
from torchvision import datasets
from torch.utils.data import DataLoader
import torch.nn.functional as F
import torch.optim as optim
import matplotlib.pyplot as plt
import numpy as np

batch_size = 64
transform = transforms.Compose([
transforms.ToTensor(), #把图像转化为张量
transforms.Normalize((0.1307,),(0.3081,)) #mniset常用均值标准差
])

train_dataset = datasets.MNIST(root='../dataset/mnist',
train = True,
download = True,
transform = transform)
trainloader = DataLoader(train_dataset,
shuffle = True,
batch_size=batch_size)
test_dataset = datasets.MNIST(root='../dataset/mnist',
train = False,
download = True,
transform = transform)
test_loader = DataLoader(test_dataset,
shuffle=False,
batch_size=batch_size)

class Net(torch.nn.Module):
def __init__(self):
super(Net,self).__init__()
self.l1=torch.nn.Linear(784,512)
self.l2=torch.nn.Linear(512,256)
self.l3=torch.nn.Linear(256,128)
self.l4=torch.nn.Linear(128,64)
self.l5=torch.nn.Linear(64,10)

def forward(self,x):
x = x.view(-1,784)
x = F.relu(self.l1(x))
x = F.relu(self.l2(x))
x = F.relu(self.l3(x))
x = F.relu(self.l4(x))
return self.l5(x) #最后一层不激活

model = Net()

criterion = torch.nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(),lr=0.01,momentum=0.5) #momentum冲量

train_losses = []
test_accuracies = []

def train(epoch):
running_loss = 0.0
for batch_size, data in enumerate(trainloader, 0):
inputs, target = data
optimizer.zero_grad()

outputs = model(inputs)
loss = criterion(outputs, target)
loss.backward()
optimizer.step()

running_loss += loss.item()
if batch_size % 300 == 299:
print('[%d, %5d] loss: %.5f' % (epoch + 1, batch_size + 1, running_loss / 300))
running_loss = 0.0

train_losses.append(running_loss / len(trainloader))


def test():
correct = 0
total = 0
with torch.no_grad():
for data in test_loader:
images, labels = data
outputs = model(images)
_, predicted = torch.max(outputs.data, dim=1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
accuracy = 100*correct /total
test_accuracies.append(accuracy)
print('Accuracy on test set: %d %%' % (100 * correct / total))

def plot_training_history():
epochs = range(1,len(train_losses)+1)
plt.figure(figsize=(12,5))

plt.subplot(1,2,1)
plt.plot(epochs,train_losses,label='Train loss',color='blue')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.title('Training Loss')
plt.legend()

plt.subplot(1, 2, 2)
plt.plot(epochs[::10], test_accuracies, label='Test accuracy', color='green')
plt.xlabel('Epochs')
plt.ylabel('Accuracy(%)')
plt.title('Testing accuracy')
plt.legend()

plt.tight_layout()
plt.show()

if __name__ == '__main__':
for epoch in range(50):
train(epoch)
if epoch % 10 == 9 :
test()

plot_training_history()

image-20250204121530962

image-20250204121500298

三、kaggle练习(Otto Group Product Classification Challenge)

Otto Group Product Classification Challenge | Kaggle

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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import torch
import numpy as np
import pandas as pd
import torch.optim as optim
import matplotlib.pyplot as plt
from torch.utils.data import Dataset
from torch.utils.data import DataLoader

class OttoDataset(Dataset):
def __init__(self,filepath,is_train = True,):
xy = pd.read_csv(filepath,skiprows=1)
if is_train:
self.y_data = torch.tensor(pd.factorize(xy.iloc[:,-1])[0],dtype=torch.long)
self.x_data = torch.tensor(xy.iloc[:,1:-1].values,dtype=torch.float32)
else:
self.x_data = torch.tensor(xy.iloc[:,1:].values,dtype=torch.float32)
self.y_data = torch.tensor(xy.iloc[:,0].values,dtype=torch.int)
self.len=len(self.x_data)
def __getitem__(self, item):
return self.x_data[item],self.y_data[item];
def __len__(self):
return self.len

train_dataset = OttoDataset('./data/train.csv')
train_dataloader = DataLoader(dataset=train_dataset,
batch_size=32,
shuffle= True,
num_workers=2)
test_dataset = OttoDataset('./data/test.csv',is_train=False)
test_dataloader = DataLoader(dataset=test_dataset,
batch_size=32,
shuffle= False,
num_workers=2)

class NetModel(torch.nn.Module):
def __init__(self):
super(NetModel,self).__init__()
self.l1 = torch.nn.Linear(93,512)
self.l2 = torch.nn.Linear(512,256)
self.l3 = torch.nn.Linear(256,128)
self.l4 = torch.nn.Linear(128,64)
self.l5 = torch.nn.Linear(64,9)
self.softmax = torch.nn.Softmax(dim=1)

def forward(self,x):
x = torch.relu(self.l1(x))
x = torch.relu(self.l2(x))
x = torch.relu(self.l3(x))
x = torch.relu(self.l4(x))
x = self.l5(x)
return x

model = NetModel()

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

epoch_list = []
train_losses = []
def train(epoch):
running_loss = 0.0
for batch_size,data in enumerate(train_dataloader,0):
inputs,labels = data
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs,labels)
running_loss += loss.item()
loss.backward()
optimizer.step()

average_loss = running_loss / len(train_dataloader)
epoch_list.append(epoch)
train_losses.append(average_loss)
print(f"Epoch [{epoch+1}/50], Loss: {average_loss:.4f}")

def test():
predict_labels = []
with torch.no_grad():
for inputs,ids in test_dataloader:
outputs = torch.softmax(model(inputs), dim=1).numpy()
predict_labels.extend([[id_.item()] + prob.tolist() for id_, prob in zip(ids, outputs)])
df = pd.DataFrame(predict_labels,columns=["id"]+[f"Class_{i}"for i in range(1,10)])
df.to_csv("./data/submission.csv",index=False)
print("Results saved to submission.csv")

def plot_training():
epochs = range(1,len(train_losses)+1)
plt.figure(figsize=(8,5))

plt.subplot(1,2,1)
plt.plot(epochs,train_losses,label='Train loss',color='blue')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.title('Training Loss')
plt.legend()
plt.tight_layout()
plt.show()

if __name__ == '__main__':
for epoch in range(50):
train(epoch)
plot_training()
test()

image-20250207172353639

image-20250207172548690

image-20250207172642033