2.1 从零实现Softmax回归
import torch
import torchvision
from torchvision import transforms
import matplotlib.pyplot as plt
from tqdm import tqdm
from torch.utils.data import DataLoader
def get_fashion_mnist_labels(labels):
"""返回Fashion-MNIST数据集的文本标签"""
text_labels = ['t-shirt', 'trouser', 'pullover', 'dress', 'coat',
'sandal', 'shirt', 'sneaker', 'bag', 'ankle boot']
labels=text_labels[labels]
return labels
def draw_fashion_mnist(row,col,num_fig,img_data):
fig,axes=plt.subplots(row,col,figsize=(row*col,4))
for i in range(num_fig):
img,label=img_data[i]
label=get_fashion_mnist_labels(label)
img=img.squeeze(0)
row_d,col_d=divmod(i,col)
ax=axes[row_d][col_d]
ax.imshow(img.numpy(),cmap='coolwarm')
ax.set_title(f"{label}")
ax.axis('off')
plt.tight_layout()
plt.show()
def Softmax(X):
X_exp=torch.exp(X)
sum_exp=X_exp.sum(dim=1,keepdim=True)
return X_exp/sum_exp
def softmax_model(X,w,b):
y_hat=torch.matmul(X.reshape((-1,w.shape[0])),w)+b
return Softmax(y_hat)
def crossentropyloss(y_hat,y):
loss=-torch.log(y_hat[range(len(y_hat)),y]).mean()
return loss
def accuray_score(y_hat,y):
y_pred=y_hat.argmax(axis=1)
cls=(y_pred==y)
return cls.float().sum().item()
def sgd(params,lr,batch_size):
with torch.no_grad():
for param in params:
param-=lr*param.grad/batch_size
param.grad.zero_()
transforms=transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.5,),(0.5,))
])
train_img=torchvision.datasets.FashionMNIST(root="../data",train=True,transform=transforms,download=True)
test_img=torchvision.datasets.FashionMNIST(root="../data",train=False,transform=transforms,download=True)
train_data=DataLoader(train_img,batch_size=200,num_workers=4,shuffle=True)
test_data=DataLoader(test_img,batch_size=200,num_workers=4)
num_inputs=784
num_outputs=10
lr=0.1
num_epochs=10
w=torch.normal(0,0.1,size=(num_inputs,num_outputs),requires_grad=True)
b=torch.zeros(num_outputs,requires_grad=True)
for epoch in range(num_epochs):
total_loss=0
total_acc_sample=0
total_samples=0
loop=tqdm(train_data,desc=f"EPOCHS[{epoch+1}/{num_epochs}]")
for X,y in loop:
X=X.reshape(X.shape[0],-1)
y_hat=softmax_model(X,w,b)
loss=crossentropyloss(y_hat,y)
loss.backward()
sgd([w,b],lr,batch_size=X.shape[0])
total_loss+=loss.item()*X.shape[0]
total_acc_sample+=accuray_score(y_hat,y)
total_samples+=X.shape[0]
test_acc_samples=0
test_samples=0
for X,y in test_data:
X=X.reshape(X.shape[0],-1)
y_hat=softmax_model(X,w,b)
test_acc_samples+=accuray_score(y_hat,y)
test_samples+=X.shape[0]
print(f"Epoch {epoch+1}: Loss: {total_loss/total_samples:.4f},Trian Accuracy: {total_acc_sample/total_samples:.4f},test Accuracy: {test_acc_samples/test_samples:.4f}")
2.2 简洁实现Softmax回归
import torch
import torchvision
from torchvision import transforms
import matplotlib.pyplot as plt
from tqdm import tqdm
import torch.nn as nn
from torch.utils.data import DataLoader
from sklearn.metrics import accuracy_score
transforms=transforms.Compose([
transforms.Resize(28),
transforms.ToTensor(),
transforms.Normalize((0.5,),(0.5,))
])
train_img=torchvision.datasets.FashionMNIST(root="../data",train=True,transform=transforms,download=True)
test_img=torchvision.datasets.FashionMNIST(root="../data",train=False,transform=transforms,download=True)
train_data=DataLoader(train_img,batch_size=200,num_workers=4,shuffle=True)
test_data=DataLoader(test_img,batch_size=200,num_workers=4)
num_inputs=784
num_outputs=10
lr=0.01
num_epochs=10
w=torch.normal(0,0.1,size=(num_inputs,num_outputs),requires_grad=True)
b=torch.zeros(num_outputs,requires_grad=True)
model=nn.Sequential(nn.Flatten(),nn.Linear(num_inputs,num_outputs))
optimizer=torch.optim.SGD(model.parameters(),lr=lr)
CEloss=nn.CrossEntropyLoss()
for epoch in range(num_epochs):
total_loss=0
total_acc_sample=0
total_samples=0
loop=tqdm(train_data,desc=f"EPOCHS[{epoch+1}/{num_epochs}]")
for X,y in loop:
X=X.reshape(X.shape[0],-1)
y_hat=model(X)
loss=CEloss(y_hat,y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
total_loss+=loss.item()*X.shape[0]
y_pred=y_hat.argmax(dim=1).detach().cpu().numpy()
y_true=y.detach().cpu().numpy()
total_acc_sample+=accuracy_score(y_pred,y_true)*X.shape[0]
total_samples+=X.shape[0]
test_acc_samples=0
test_samples=0
for X,y in test_data:
X=X.reshape(X.shape[0],-1)
y_hat=model(X)
y_pred=y_hat.argmax(dim=1).detach().cpu().numpy()
y_true=y.detach().cpu().numpy()
test_acc_samples+=accuracy_score(y_pred,y_true)*X.shape[0]
test_samples+=X.shape[0]
print(f"Epoch {epoch+1}: Loss: {total_loss/total_samples:.4f},Trian Accuracy: {total_acc_sample/total_samples:.4f},test Accuracy: {test_acc_samples/test_samples:.4f}")