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_expdef softmax_model(X,w,b):y_hat=torch.matmul(X.reshape((-1,w.shape[0])),w)+breturn 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_sizeparam.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=0total_acc_sample=0total_samples=0loop=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=0test_samples=0for 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=0total_acc_sample=0total_samples=0loop=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=0test_samples=0for 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}")