<jupyter_start><jupyter_text>Mnist数据集的读取<jupyter_code>!pip install git+https://github.com/d2l-ai/d2l-zh@release  # installing d2l
%matplotlib inline
import torch
import torchvision
from torch.utils import data
from torchvision import transforms
from d2l import torch as d2l

d2l.use_svg_display()
trans = transforms.ToTensor()
mnist_train = torchvision.datasets.FashionMNIST(
    root="../data", train=True, transform=trans, download=True)
mnist_test = torchvision.datasets.FashionMNIST(
    root="../data", train=False, transform=trans, download=True)
def get_fashion_mnist_labels(labels):  
    text_labels = ['t-shirt', 'trouser', 'pullover', 'dress', 'coat',
                   'sandal', 'shirt', 'sneaker', 'bag', 'ankle boot']
    return [text_labels[int(i)] for i in labels]
def show_images(imgs, num_rows, num_cols, titles=None, scale=1.5):  
    figsize = (num_cols * scale, num_rows * scale)
    _, axes = d2l.plt.subplots(num_rows, num_cols, figsize=figsize)
    axes = axes.flatten()
    for i, (ax, img) in enumerate(zip(axes, imgs)):
        if torch.is_tensor(img):
            # 图片张量
            ax.imshow(img.numpy())
        else:
            # PIL图片
            ax.imshow(img)
        ax.axes.get_xaxis().set_visible(False)
        ax.axes.get_yaxis().set_visible(False)
        if titles:
            ax.set_title(titles[i])
    return axes
X, y = next(iter(data.DataLoader(mnist_train, batch_size=18)))
show_images(X.reshape(18, 28, 28), 2, 9, titles=get_fashion_mnist_labels(y));
batch_size=256
def get_dataloader_works():
  return 2

train_iter=data.DataLoader(mnist_train,batch_size,shuffle=True,num_workers=get_dataloader_works())
timer=d2l.Timer()
for X,y in train_iter:
  continue
f'{timer.stop():.2f} sec' #f-string,{}内为可替换的内容<jupyter_output><empty_output><jupyter_text>对以上操作进行整合<jupyter_code>def load_data_fashion_mnist(batch_size,resize=None):
  trans=[transforms.ToTensor()]
  if resize:
    trans.insert(0,transforms.Resize(resize))
  trans=transforms.Compose(trans)
  mnist_train = torchvision.datasets.FashionMNIST(
    root="../data", train=True, transform=trans, download=True)
  mnist_test = torchvision.datasets.FashionMNIST(
    root="../data", train=False, transform=trans, download=True)
  return (data.DataLoader(mnist_train,batch_size,shuffle=True,
              num_workers=get_dataloader_works()),
      data.DataLoader(mnist_test,batch_size,shuffle=True,
              num_workers=get_dataloader_works()))
import torch
from IPython import display
from d2l import torch as d2l
batch_size=256
train_iter,test_iter=d2l.load_data_fashion_mnist(batch_size)
num_inputs=784
num_outputs=10

W=torch.normal(0,0.01,size=(num_inputs,num_outputs),requires_grad=True)
b=torch.zeros(num_outputs,requires_grad=True)<jupyter_output><empty_output><jupyter_text>softmax的三个步骤1. 对每一项求幂(exp)2. 对每一行求和(每个batch是一行),得到规范化常数3. 每一项除以规范化常数(和的结果为1)$softmax(X)_{ij}=\frac{e^{X_{ij}}}{∑_ke^{X_{ik}}} $<jupyter_code>#定义softmax函数
def softmax(X):
  X_exp=torch.exp(X)
  partition=X_exp.sum(1,keepdims=True)
  return X_exp/partition
#测试一下
x=torch.normal(0,1,(2,6))
x_prob=softmax(x)
print(x_prob,"\n",x_prob.sum(1))<jupyter_output>tensor([[0.2198, 0.2886, 0.0512, 0.2438, 0.0850, 0.1116],
        [0.0682, 0.0888, 0.4506, 0.0956, 0.0692, 0.2275]]) 
 tensor([1.0000, 1.0000])<jupyter_text>定义模型实现softmax回归模型<jupyter_code>#使用reshape函数将图片展开为向量(一维)
def net(X):
  return softmax(torch.matmul(X.reshape((-1,W.shape[0])),W)+b)<jupyter_output><empty_output><jupyter_text>损失函数这里使用**交叉熵**损失函数 **交叉熵**  $$ L=\frac{1}{N}∑L_i=-\frac{1}{N}\sum_{i}\sum_{c=1}^{M}y_{ic}log(p_{ic}) $$where:* $M:类别数量$* $y_{ic}:符号函数,如果样本i的真实值等于类别c取1,否则取0$* $p_{ic}:样本i属于类别c的概率$<jupyter_code>y = torch.tensor([0, 2])
y_hat = torch.tensor([[0.1, 0.3, 0.6], [0.3, 0.2, 0.5]])
y_hat[[0, 1], y]
#取y_hat中的[0][0]和[1][2]
def cross_entropy(y_hat,y):
  return -torch.log(y_hat[range(len(y_hat)),y])

cross_entropy(y_hat,y)<jupyter_output><empty_output><jupyter_text>分类精度<jupyter_code>def accuracy(y_hat,y):
  if len(y_hat.shape)>1 and y_hat.shape[1]>1:
    y_hat=y_hat.argmax(axis=1)
  cmp=y_hat.type(y.dtype)==y
  return float(cmp.type(y.dtype).sum())
accuracy(y_hat,y)/len(y)
def evaluate_accuracy(net,data_iter):
  if isinstance(net,torch.nn.Module):
    net.eval()
  metric=Accumulator(2)
  for X,y in data_iter:
    metric.add(accuracy(net(X),y),y.numel())
  return metric[0]/metric[1]
class Accumulator: 
  def __init__(self, n):
    self.data = [0.0] * n

  def add(self, *args):
    self.data = [a + float(b) for a, b in zip(self.data, args)]

  def reset(self):
    self.data = [0.0] * len(self.data)

  def __getitem__(self, idx):
    return self.data[idx]
evaluate_accuracy(net,test_iter)<jupyter_output>/usr/local/lib/python3.7/dist-packages/torch/utils/data/dataloader.py:481: UserWarning: This DataLoader will create 4 worker processes in total. Our suggested max number of worker in current system is 2, which is smaller than what this DataLoader is going to create. Please be aware that excessive worker creation might get DataLoader running slow or even freeze, lower the worker number to avoid potential slowness/freeze if necessary.
  cpuset_checked))<jupyter_text>训练一个周期的函数<jupyter_code>def train_epoch(net,train_iter,loss,updater): 
#train_iter 训练数据集迭代器,loss 损失函数,updater 对W和b进行更新的函数
  if isinstance(net,torch.nn.Module):
    net.train()
  metric=Accumulator(3)
  for X,y in train_iter:
    y_hat=net(X)
    l=loss(y_hat,y)
    if isinstance(updater,torch.optim.Optimizer):
      updater.zero_grad()
      l.mean().backward()
      updater.step()
    else:
      l.sum().backward()
      updater(X.shape[0])
    metric.add(float(l.sum()),accuracy(y_hat,y),y.numel())
  return metric[0]/metric[2],metric[1]/metric[2]
def train_epoch_ch3(net, train_iter, loss, updater):  #ave
    """训练模型一个迭代周期（定义见第3章）"""
    # 将模型设置为训练模式
    if isinstance(net, torch.nn.Module):
        net.train()
    # 训练损失总和、训练准确度总和、样本数
    metric = Accumulator(3)
    for X, y in train_iter:
        # 计算梯度并更新参数
        y_hat = net(X)
        l = loss(y_hat, y)
        if isinstance(updater, torch.optim.Optimizer):
            # 使用PyTorch内置的优化器和损失函数
            updater.zero_grad()
            l.mean().backward()
            updater.step()
        else:
            # 使用定制的优化器和损失函数
            l.sum().backward()
            updater(X.shape[0])
        metric.add(float(l.sum()), accuracy(y_hat, y), y.numel())
    # 返回训练损失和训练精度
    return metric[0] / metric[2], metric[1] / metric[2]<jupyter_output><empty_output><jupyter_text>Animator绘制数据,展示迭代成功<jupyter_code>class Animator:
  def __init__(self, xlabel=None, ylabel=None, legend=None, xlim=None,
            ylim=None, xscale='linear', yscale='linear',
            fmts=('-', 'm--', 'g-.', 'r:'), nrows=1, ncols=1,
            figsize=(3.5, 2.5)):
    if legend is None:
      legend=[]
    d2l.use_svg_display()
    self.fig, self.axes = d2l.plt.subplots(nrows, ncols, figsize=figsize)
    if nrows * ncols == 1:
      self.axes = [self.axes, ]
    self.config_axes = lambda: d2l.set_axes(
      self.axes[0], xlabel, ylabel, xlim, ylim, xscale, yscale, legend)
    self.X, self.Y, self.fmts = None, None, fmts
  
  def add(self, x, y):
    # 向图表中添加多个数据点
    if not hasattr(y, "__len__"):
      y = [y]
    n = len(y)
    if not hasattr(x, "__len__"):
      x = [x] * n
    if not self.X:
      self.X = [[] for _ in range(n)]
    if not self.Y:
      self.Y = [[] for _ in range(n)]
    for i, (a, b) in enumerate(zip(x, y)):
      if a is not None and b is not None:
        self.X[i].append(a)
        self.Y[i].append(b)
    self.axes[0].cla()
    for x, y, fmt in zip(self.X, self.Y, self.fmts):
      self.axes[0].plot(x, y, fmt)
    self.config_axes()
    display.display(self.fig)
    display.clear_output(wait=True)<jupyter_output><empty_output><jupyter_text>开始训练<jupyter_code>def train(net,train_iter,test_iter,loss,num_epochs,updater):
  animator=Animator(xlabel='epoch', xlim=[1, num_epochs], ylim=[0.3, 0.9],
            legend=['train loss', 'train acc', 'test acc'])
  for epoch in range(num_epochs):
    train_metrics=train_epoch_ch3(net,train_iter,loss,updater)
    test_acc=evaluate_accuracy(net,test_iter)
    animator.add(epoch+1,train_metrics+(test_acc,))
    train_loss,train_acc=train_metrics
    
    #assert train_loss<0.5, train_loss #这里会报错,不太懂 train_loss 要控制在0.5一下的原因
    assert train_acc<=1 and train_acc>0.7, train_acc
    assert test_acc<=1 and test_acc>0.7, test_acc

lr=0.1#learning rate 学习率
def updater(batch_size):
  return d2l.sgd([W,b],lr,batch_size)
num_epochs=10
train(net,train_iter,test_iter,cross_entropy,num_epochs,updater)
def predict_ch3(net, test_iter, n=6): 
  for X, y in test_iter:
    break
  trues = d2l.get_fashion_mnist_labels(y)
  preds = d2l.get_fashion_mnist_labels(net(X).argmax(axis=1))
  titles = [true +'\n' + pred for true, pred in zip(trues, preds)]
  d2l.show_images(X[0:n].reshape((n, 28, 28)), 1, n, titles=titles[0:n])

predict_ch3(net, test_iter,n=10)<jupyter_output>/usr/local/lib/python3.7/dist-packages/torch/utils/data/dataloader.py:481: UserWarning: This DataLoader will create 4 worker processes in total. Our suggested max number of worker in current system is 2, which is smaller than what this DataLoader is going to create. Please be aware that excessive worker creation might get DataLoader running slow or even freeze, lower the worker number to avoid potential slowness/freeze if necessary.
  cpuset_checked))<jupyter_text>使用深度学习框架的API实现<jupyter_code>from torch import nn

bathch_size=256
train_iter,test_iter=d2l.load_data_fashion_mnist(batch_size)
net=nn.Sequential(nn.Flatten(),nn.Linear(784,10))

def init_weights(m):
  if type(m)==nn.Linear:
    nn.init.normal_(m.weight,std=0.01)

net.apply(init_weights)
loss=nn.CrossEntropyLoss(reduction='none')
trainer=torch.optim.SGD(net.parameters(),lr=0.1)
num_epochs=10
d2l.train_ch3(net,train_iter,test_iter,loss,num_epochs,trainer)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1480359487024134, 'fraction_numerical': 0.02585075229728365, 'mean_word_length': 4.49916712937257, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 42, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '10', 'dir': 'jupyter-structured-clean-dedup', 'id': '608087', 'license': 'MIT', 'n_tokens_mistral': 4217, 'n_tokens_neox': 4221, 'n_words': 675, 'path': 'MLEveryday12.ipynb', 'repo_name': 'marongkang/MLeveryday', 'size': '9903'}