当前位置: 首页 > news >正文

Softmax 回归 + 损失函数 + 图片分类数据集

Softmax 回归

在这里插入图片描述
softmax 回归是机器学习另外一个非常经典且重要的模型,是一个分类问题。

下面先解释一下分类和回归的区别:
在这里插入图片描述
在这里插入图片描述
简单来说,分类问题从回归的单输出变成了多输出,输出的个数等于类别的个数。
在这里插入图片描述
实际上,对于分类来说,我们不关心它们之间实际的值,我们关心的是:模型是否对正确类别的置信度特别的大
在这里插入图片描述
虽然上述没有要求 O i O_i Oi 是一个什么样的值,但是如果我们将值放在合适的区间,也会让后续的处理变得更加的简单,比如下面我们希望模型的输出是一个概率:在这里插入图片描述
在这里插入图片描述
上述要是你使用了 o n e − h o t one-hot onehot 编码的话,只有当 i = y i=y i=y时, y i = 1 y_i = 1 yi=1,否则就是0。
在这里插入图片描述

损失函数

损失函数是用来衡量预测值与真实值之间的区别,是机器学习里面一个非常重要的概念。
在这里插入图片描述

1. L2 Loss(均方损失)

在这里插入图片描述
蓝色的线表示 y = 0 y=0 y=0 时变换我的 预测值 y ′ y' y 所生成的函数,可以看出来是一个二次函数。绿色是一个似然函数,似然函数取得最大值表明取该参数模型最合理。橙色的表示的是损失函数的梯度,由于是一次函数,穿过原点。

由上述可以发现,当预测值与真实值距离比较远的时候,梯度比较的大,则对参数的更新是比较的多的,当越靠近原点的时候,梯度的绝对值就会越小,对参数的更新就会越来越小。但这可能并不是一件好事,因为在离原点越远的地方,我可能并不希望需要那么大的梯度来更新我的参数。因此也可以考虑下面的 L1 Loss

L1 Loss

在这里插入图片描述
当然也是可以提出新的损失函数来结合上述两种损失函数的好处。
在这里插入图片描述
在这里插入图片描述
上述损失函数定义的好处就是:当预测值与真实值差别比较大的时候,我可以以均匀的力度
往回拉。当两者越来越接近时,我可以使得拉的力度越来越小,从而不会出现数值上的问题。

图片分类数据集

下面使用 Fashion-MNIST 数据集,展示对数据集的一般操作:

首先导入所需的库:

%matplotlib inline
import torch
import torchvision
from torch.utils import data
from torchvision import transforms
from d2l import torch as d2ld2l.use_svg_display() 
# 使用svg来显示图片

接着我们可以通过框架中的内置函数将Fashion-MNIST数据集下载并读取到内存中

# 通过ToTensor实例将图像数据从PIL类型变换成32位浮点数格式,
# 并除以255使得所有像素的数值均在0~1之间
trans = transforms.ToTensor() # 预处理,将图片转换成tensor
mnist_train = torchvision.datasets.FashionMNIST(root="../data", train=True, transform=trans, download=True)
# transform=trans希望得到的是一个tensor而不是一张图片
mnist_test = torchvision.datasets.FashionMNIST(root="../data", train=False, transform=trans, download=True)

Fashion-MNIST由10个类别的图像组成,每个类别由训练数据集(train dataset)中的6000张图像和测试数据集(test dataset)中的1000张图像组成。因此,训练集和测试集分别包含60000和10000张图像。测试数据集不会用于训练,只用于评估模型性能。
在这里插入图片描述
每个输入图像的高度和宽度均为28像素。
数据集由灰度图像组成,其通道数为1。
为了简洁起见,将高度 h h h像素、宽度 w w w像素图像的形状记为 h × w h \times w h×w或( h h h, w w w)。
在这里插入图片描述
接着定义两个可视化数据集的函数

Fashion-MNIST中包含的10个类别,分别为t-shirt(T恤)、trouser(裤子)、pullover(套衫)、dress(连衣裙)、coat(外套)、sandal(凉鞋)、shirt(衬衫)、sneaker(运动鞋)、bag(包)和ankle boot(短靴)。

以下函数用于在数字标签索引及其文本名称之间进行转换。

def get_fashion_mnist_labels(labels):  #@save"""返回Fashion-MNIST数据集的文本标签"""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):  #@save"""绘制图像列表"""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

以下展示训练数据集中前几个样本的图像及其相应的标签。
在这里插入图片描述
为了使我们在读取训练集和测试集时更容易,我们使用内置的数据迭代器,而不是从零开始创建。
在每次迭代中,数据加载器每次都会读取一小批量数据,大小为batch_size

通过内置数据迭代器,我们可以随机打乱了所有样本,从而无偏见地读取小批量。

batch_size = 256def get_dataloader_workers():  #@save"""使用4个进程来读取数据"""return 4train_iter = data.DataLoader(mnist_train, batch_size, shuffle=True,num_workers=get_dataloader_workers())timer = d2l.Timer() # 用来测试速度
for X, y in train_iter:continue
f'{timer.stop():.2f} sec'

在这里插入图片描述
在模型训练之前,一般都是需要测试数据读取的速度,数据读取的速度需要比模型的训练速度更快才好。

基于上述内容,现在我们定义load_data_fashion_mnist函数,用于获取和读取Fashion-MNIST数据集。这个函数返回训练集验证集的数据迭代器。此外,这个函数还接受一个可选参数resize,用来将图像大小调整为另一种形状。

def load_data_fashion_mnist(batch_size, resize=None):  #@save"""下载Fashion-MNIST数据集,然后将其加载到内存中"""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_workers()),data.DataLoader(mnist_test, batch_size, shuffle=False,num_workers=get_dataloader_workers()))

在这里插入图片描述

Softmax 回归从0开始实现

import torch
from IPython import display
from d2l import torch as d2lbatch_size = 256 # 每次随机读取256张图片
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size) # 前面实现过

由于图像是12828的,但是对于softmax来说,输入的需要是一个向量。(但是这种操作会损失很多空间信息,卷积部分解决。)因此我们将展平每个图像,把它们看作长度为784的向量。数据集有十个类别,因此网络输出维度就是10。

num_inputs = 784 # 将空间拉长,28*28拉成784的一个向量
num_outputs = 10W = torch.normal(0, 0.01, size=(num_inputs, num_outputs), requires_grad=True)
# 行数为输入的个数,列数等于输出的个数
b = torch.zeros(num_outputs, requires_grad=True)
# 对每一个输出,都需要有一个偏移

下面定义 softmax 操作:
在这里插入图片描述实现softmax由三个步骤组成:

  1. 对每个项求幂(使用exp);
  2. 对每一行求和(小批量中每个样本是一行),得到每个样本的规范化常数;
  3. 将每一行除以其规范化常数,确保结果的和为1。

表达式如下:
s o f t m a x ( X ) i j = exp ⁡ ( X i j ) ∑ k exp ⁡ ( X i k ) . \mathrm{softmax}(\mathbf{X})_{ij} = \frac{\exp(\mathbf{X}_{ij})}{\sum_k \exp(\mathbf{X}_{ik})}. softmax(X)ij=kexp(Xik)exp(Xij).分母或规范化常数,有时也称为配分函数(其对数称为对数-配分函数)。该名称来自统计物理学中一个模拟粒子群分布的方程。

def softmax(X):X_exp = torch.exp(X) # 对X中的每个元素作指数运算partition = X_exp.sum(1, keepdim=True) # 按照每一行进行求和return X_exp / partition  # 这里应用了广播机制

在这里插入图片描述
定义softmax操作后,可以实现softmax回归模型
下面的代码定义了输入如何通过网络映射到输出。
注意,将数据传递到模型之前,我们使用reshape函数将每张原始图像展平为向量。

def net(X):return softmax(torch.matmul(X.reshape((-1, W.shape[0])), W) + b)

首先回顾一下交叉熵:
交叉熵采用真实标签的预测概率的负对数似然。这里我们不使用Python的for循环迭代预测(这往往是低效的),而是通过一个运算符选择所有元素。

下面,**创建一个数据样本y_hat,其中包含2个样本在3个类别的预测概率,以及它们对应的标签y。**有了y,我们知道在第一个样本中,第一类是正确的预测;而在第二个样本中,第三类是正确的预测。然后(使用y作为y_hat中概率的索引),我们选择第一个样本中第一个类的概率和第二个样本中第三个类的概率。

y = torch.tensor([0, 2]) # 表示两个样本的真实标签分别为0、2
y_hat = torch.tensor([[0.1, 0.3, 0.6], [0.3, 0.2, 0.5]])
y_hat[[0, 1], y] 
# 对第0个样本,拿出y[0]对应的那个元素,对第一个样本,拿出y[1]对应的那个元素
# [0, 1] 是一个索引列表,表示要选取 y_hat 中的第一行和第二行。

在这里插入图片描述
基于上述,我们下面来实现交叉熵损失函数:

# 了解交叉熵公式和代码上述原理,一行代码即可完成。
def cross_entropy(y_hat, y):return - torch.log(y_hat[range(len(y_hat)), y])cross_entropy(y_hat, y)

在这里插入图片描述
由于上述是分类问题,因此需要将预测类别与真实 y y y 元素进行比较:

def accuracy(y_hat, y):  #@save"""计算预测正确的数量"""# 要是 y_hat 是一个二维矩阵且列数也大于1 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  # 将 y_hat 转换为 y 的数据类型,然后作比较return float(cmp.type(y.dtype).sum()) # 返回预测正确的样本数

我们将继续使用之前定义的变量y_haty分别作为预测的概率分布和标签。可以看到,第一个样本的预测类别是2(该行的最大元素为0.6,索引为2),这与实际标签0不一致。第二个样本的预测类别是2(该行的最大元素为0.5,索引为2),这与实际标签2一致。因此,这两个样本的分类精度率为0.5。
在这里插入图片描述
同样,对于任意数据迭代器data_iter可访问的数据集,可以评估在任意模型net的精度

def evaluate_accuracy(net, data_iter):  #@save"""计算在指定数据集上模型的精度"""if isinstance(net, torch.nn.Module):net.eval()  # 将模型设置为评估模式metric = Accumulator(2)  # 正确预测数、预测总数with torch.no_grad():for X, y in data_iter:metric.add(accuracy(net(X), y), y.numel())return metric[0] / metric[1]

这里定义一个实用程序类Accumulator,用于对多个变量进行累加。在上面的evaluate_accuracy函数中,我们在(Accumulator实例中创建了2个变量,分别用于存储正确预测的数量和预测的总数量)。当我们遍历数据集时,两者都将随着时间的推移而累加。

class Accumulator:  #@save"""在n个变量上累加"""def __init__(self, n):self.data = [0.0] * ndef 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]

在这里插入图片描述
下面就可以进行 softmax 的回归训练了:

def train_epoch_ch3(net, train_iter, loss, updater):  #@save"""训练模型一个迭代周期(定义见第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]

在展示训练函数的实现之前,我们[定义一个在动画中绘制数据的实用程序类]Animator

class Animator:  #@save"""在动画中绘制数据"""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, ]# 使用lambda函数捕获参数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, fmtsdef add(self, x, y):# 向图表中添加多个数据点if not hasattr(y, "__len__"):y = [y]n = len(y)if not hasattr(x, "__len__"):x = [x] * nif 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)

下面开始训练:

def train_ch3(net, train_iter, test_iter, loss, num_epochs, updater):  #@save"""训练模型(定义见第3章)"""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_metricsassert train_loss < 0.5, train_lossassert train_acc <= 1 and train_acc > 0.7, train_accassert test_acc <= 1 and test_acc > 0.7, test_acc

[小批量随机梯度下降来优化模型的损失函数],设置学习率为0.1

lr = 0.1def updater(batch_size):return d2l.sgd([W, b], lr, batch_size)

在这里插入图片描述
对图像进行预测:

def predict_ch3(net, test_iter, n=6):  #@save"""预测标签"""for X, y in test_iter:breaktrues = 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)

在这里插入图片描述

Softmax 回归的简洁实现

通过深度学习框架的高级API也能更方便地实现softmax回归模型:

import torch
from torch import nn
from d2l import torch as d2lbatch_size = 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)

Softmax 回归的输出层是一个全连接层

# PyTorch不会隐式地调整输入的形状。因此,
# 我们在线性层前定义了展平层(flatten),来调整网络输入的形状
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);

在交叉熵损失函数中传递未规范化的预测,并同时计算softmax及其对数

loss = nn.CrossEntropyLoss(reduction='none')# 不进行任何减少操作,返回每个样本的损失值。

使用学习率为0.1的小批量随机梯度下降作为优化算法

trainer = torch.optim.SGD(net.parameters(), lr=0.1)

训练,重用之前编写的函数:
在这里插入图片描述

QA思考

Q1:softlabel训练策略。

上述被称为软标签,旨在通过使用非硬性(即不是0或1的绝对分类结果)的目标标签来提高模型的泛化能力和鲁棒性。
传统的分类任务中,目标标签通常是one-hot编码的形式,即对于每个样本,正确的类别标记为1,其他类别标记为0。但是实际上对于边界值是很难达到的,比如对于softmax函数而言:
softmax ( z i ) = e z i ∑ j = 1 n e z j \text{softmax}(z_i) = \frac{e^{z_i}}{\sum_{j=1}^{n} e^{z_j}} softmax(zi)=j=1nezjezi
要想使其输出为 1 ,则需要某一个 z i z_i zi ,趋近于无穷才行。

而softlabel则允许这些标签值位于(0, 1)之间,并且所有类别的概率之和通常为1。这意味着即使是错误的类别也可能被赋予一定的概率,从而向模型传达“某种程度上的正确”。比如我可以认为0.9 就是正确,0.1 就是不正确。

Q2 : softmax 回归和 logistic 回归的联系。
可以认为logistic是softmax的特例,也就是logistic是一个两分类的问题,只需要输出一个类别的概率 P P P 即可,剩下的直接 1 − P 1-P 1P 即可。但是在实际的分类问题中,两分类的问题很少。

Q3 : 在 Accuracy函数中为啥不把除以 len(y) 做完呢?
在 Accuracy 函数中,不能直接除以 len(y),因为最后一个 batch 的样本数量可能会少于设定的 batch size。为了确保准确率计算的正确性,应该根据当前 batch 实际包含的样本数量进行归一化,而不是固定地使用完整的 batch size。

补充:
考虑到李沐老师的视线中使用到了d2l,且是在jupyter上面进行实现的,但是我现在不想用d2l,以及需要再Pycharm上面编写,于是我根据上述代码编写了下面的代码,结果也能很好的复现李沐老师代码的结果。

import torch
import torchvision
from torchvision import transforms
from torch.utils import data
import matplotlib.pyplot as pltclass Animator:def __init__(self, xlabel=None, ylabel=None, legend=None, xlim=None,ylim=None, xscale='linear', yscale='linear',fmts=('-', 'm--', 'g-.', 'r:'), figsize=(3.5, 2.5)):if legend is None:legend = []self.xlabel = xlabelself.ylabel = ylabelself.legend = legendself.xlim = xlimself.ylim = ylimself.xscale = xscaleself.yscale = yscaleself.fmts = fmtsself.figsize = figsizeself.X, self.Y = [], []def add(self, x, y):if not hasattr(y, "__len__"):y = [y]n = len(y)if not hasattr(x, "__len__"):x = [x] * nif 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)def show(self):plt.figure(figsize=self.figsize)for x_data, y_data, fmt in zip(self.X, self.Y, self.fmts):plt.plot(x_data, y_data, fmt)plt.xlabel(self.xlabel)plt.ylabel(self.ylabel)if self.legend:plt.legend(self.legend)if self.xlim:plt.xlim(self.xlim)if self.ylim:plt.ylim(self.ylim)plt.xscale(self.xscale)plt.yscale(self.yscale)plt.grid()plt.show()def get_dataloader_workers():return 0  # 禁用多进程加载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("./data", train=True, transform=trans, download=True)mnist_test = torchvision.datasets.FashionMNIST("./data", train=False, transform=trans, download=True)return (data.DataLoader(mnist_train, batch_size, shuffle=True, num_workers=get_dataloader_workers()),data.DataLoader(mnist_test, batch_size, shuffle=False, num_workers=get_dataloader_workers()))# softmax 实现
def softmax(X):X_exp = torch.exp(X)partition = X_exp.sum(1, keepdim=True)return X_exp / partition# 回归模型
def net(X):return softmax(torch.matmul(X.reshape((-1, W.shape[0])), W) + b)# 交叉熵损失函数
def cross_entropy(y_hat, y):return -torch.log(y_hat[range(len(y_hat)), y])# 预测正确的数量
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) == yreturn float(cmp.type(y.dtype).sum())class Accumulator:def __init__(self, n):self.data = [0.0] * ndef 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]def evaluate_accuracy(net, data_iter):if isinstance(net, torch.nn.Module):net.eval()metric = Accumulator(2)with torch.no_grad():for X, y in data_iter:metric.add(accuracy(net(X), y), y.numel())return metric[0] / metric[1]def train_epoch_ch3(net, train_iter, loss, updater):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_ch3(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_metricsassert train_loss < 0.5, train_lossassert train_acc <= 1 and train_acc > 0.7, train_accassert test_acc <= 1 and test_acc > 0.7, test_accanimator.show()  # 展示最终结果图def sgd(params, lr, batch_size):with torch.no_grad():for param in params:param -= lr * param.grad / batch_sizeparam.grad.zero_()def updater(batch_size):return sgd([W, b], lr, batch_size)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 = 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(), cmap='gray')else:ax.imshow(img, cmap='gray')ax.axes.get_xaxis().set_visible(False)ax.axes.get_yaxis().set_visible(False)if titles:ax.set_title(titles[i])plt.show()def predict_ch3(net, test_iter, n=6):for X, y in test_iter:breaktrues = get_fashion_mnist_labels(y)preds = get_fashion_mnist_labels(net(X).argmax(axis=1))titles = [true + '\n' + pred for true, pred in zip(trues, preds)]show_images(X[0:n].reshape((n, 28, 28)), 1, n, titles=titles[0:n])if __name__ == "__main__":# 定义超参数batch_size = 256num_epochs = 10lr = 0.1# 加载数据train_iter, test_iter = load_data_fashion_mnist(batch_size)# 初始化模型参数num_inputs = 784num_outputs = 10W = torch.normal(0, 0.1, size=(num_inputs, num_outputs), requires_grad=True)b = torch.zeros(num_outputs, requires_grad=True)# 训练模型train_ch3(net, train_iter, test_iter, cross_entropy, num_epochs, updater)# 测试模型并显示预测结果predict_ch3(net, test_iter)

相关文章:

Softmax 回归 + 损失函数 + 图片分类数据集

Softmax 回归 softmax 回归是机器学习另外一个非常经典且重要的模型&#xff0c;是一个分类问题。 下面先解释一下分类和回归的区别&#xff1a; 简单来说&#xff0c;分类问题从回归的单输出变成了多输出&#xff0c;输出的个数等于类别的个数。 实际上&#xff0c;对于分…...

基于云服务器的数仓搭建-hive/spark安装

mysql本地安装 安装流程&#xff08;内存占用200M&#xff0c;升至2.1G&#xff09; # 将资料里mysql文件夹及里面所有内容上传到/opt/software/mysql目录下 mkdir /opt/software/mysql cd /opt/software/mysql/ # 待上传文件 install_mysql.sh mysql-community-client-8.0.3…...

YOLO历代发展 图像增强方式 架构

YOLO1 YOLOV5 数据增强 mosaic 仿射变换(Affine)、透视变换(Perspective) 网络搭建...

Spring AI Alibaba EmbeddingModel使用

一、嵌入模型 (Embedding Model)简介 1、核心概念 嵌入模型&#xff08;EmbeddingModel&#xff09;是嵌入过程中采用的模型。 当前 EmbeddingModel的接口主要用于将文本转换为数值向量&#xff0c;接口的设计主要围绕这两个目标展开&#xff1a; 可移植性&#xff1a; 该接口…...

C++入门五式——类和对象(下)

目录 再探构造函数——初始化列表 类型转换 static成员 友元函数 内部类 匿名对象 再探构造函数——初始化列表 之前我们实现构造函数时&#xff0c;初始化成员变量主要使用函数体内赋值&#xff0c;构造函数初始化还有一种方式&#xff0c;就是初始化列表。 //初始化列…...

Spring的SPEL(Spring Expression Language)的使用说明,包含语法、示例和常见场景

以下是Spring的SPEL&#xff08;Spring Expression Language&#xff09;的使用说明&#xff0c;包含语法、示例和常见场景&#xff1a; 1. 基本语法 变量引用 表达式&#xff1a;#{变量名}&#xff08;如#{systemProperties[os.name]}&#xff09;作用域&#xff1a;在Sprin…...

Linux应用:线程进阶

线程同步之信号量 信号量&#xff08;Semaphore&#xff09;是一个整型的计数器&#xff0c;用于控制对共享资源的访问。它通过 PV 操作来实现同步&#xff0c;P 操作将信号量的值减 1&#xff0c;如果值小于 0 则线程阻塞&#xff1b;V 操作将信号量的值加 1&#xff0c;如果…...

策略模式 (Strategy)

策略模式 (Strategy) 应用场景&#xff1a;用于处理不同的任务配置参数。在你的任务中&#xff0c;可能会有不同的任务类型&#xff0c;每个任务类型可能有不同的单位&#xff08;比如米、毫米&#xff09;或不同的处理方式。策略模式可以让你根据不同的任务类型选择不同的处理…...

【YOLOv8】YOLOv8改进系列(10)----替换主干网络之UniRepLKNet

主页&#xff1a;HABUO&#x1f341;主页&#xff1a;HABUO &#x1f341;YOLOv8入门改进专栏&#x1f341; &#x1f341;如果再也不能见到你&#xff0c;祝你早安&#xff0c;午安&#xff0c;晚安&#x1f341; 【YOLOv8改进系列】&#xff1a; YOLOv8改进系列&#xff0…...

mathtype一些用法总结

1.一个是公式旁边加入||&#xff0c;一般使用键盘直接打入的会比较小&#xff0c;mathtype中的会好看很多&#xff0c;打开这个栏目&#xff0c;会看到有很多。 2.另外是带^符号&#xff0c;在字符上面带没有办法直接带&#xff0c;所以可以在mathtype中先加帽子&#xff0c;然…...

1、SQL注入攻击的防范

原文地址: SQL注入攻击的防范 更多内容请关注&#xff1a;代码安全 PHP安全编码——书写安全的代码 1、SQL注入攻击的防范 提问 问题1&#xff1a;什么是SQL注入攻击&#xff1f; 问题2&#xff1a;有几种简单方法防范SQL注入攻击&#xff1f; 问题3&#xff1a;mys…...

核心知识——论文总结

引入 本文我们会针对论文中的核心内容进行总结&#xff0c;加深小伙伴对于Spark的理解。而通过Spark的论文&#xff0c;重点需要掌握理解如下内容&#xff1a; Spark 里核心的 RDD 是一个什么概念&#xff0c;它是通过什么方式来优化分布式数据处理的&#xff0c;它的设计思路…...

HTTP 核心知识点整理

1. HTTP 基础 ​定义&#xff1a;HTTP&#xff08;HyperText Transfer Protocol&#xff09;是应用层协议&#xff0c;基于 ​请求-响应模型&#xff0c;用于客户端&#xff08;浏览器&#xff09;与服务器之间的通信。​特点&#xff1a; ​无状态&#xff1a;每次请求独立&a…...

什么是矩阵账号

矩阵账号是指在同一平台或多个平台上&#xff0c;围绕同一品牌或个人&#xff0c;创建的多个相互关联、协同工作的账号组合。这些账号虽然独立&#xff0c;但在内容定位和运营策略上有所区分&#xff0c;同时又相互引流&#xff0c;共同形成一个网络结构&#xff0c;类似于矩阵…...

【6】VS Code 新建上位机项目---项目分层

【6】VS Code 新建上位机项目---项目分层 1 项目分层(layer)2 项目分层实现数据插入SQL3 项目分层实现 (实体类封装参数)4 项目分层的实现SQL查询数据1 项目分层(layer) 表示层(UI):与用户交互使用。比如按钮,输入信息等;业务层(BLL):传递数据,业务逻辑。根据用户需…...

EspressoSample深度解析:在CircleCI上高效运行Android UI测试

项目背景与简介 EspressoSample项目位于GitHub上的circleci/EspressoSample仓库&#xff0c;该项目旨在展示如何在CircleCI平台上配置和使用Espresso进行Android应用的UI测试。 项目结构与环境准备 项目结构 EspressoSample项目遵循典型的Android项目结构&#xff0c;包含a…...

【每日论文】MetaSpatial: Reinforcing 3D Spatial Reasoning in VLMs for the Metaverse

下载PDF或查看论文&#xff0c;请点击&#xff1a; LlamaFactory - huggingface daily paper - 每日论文解读 | LlamaFactory | LlamaFactory探索LlamaFactory&#xff0c;为你解读AI前沿技术文章&#xff0c;快速掌握最新技术动态https://www.llamafactory.cn/daily-paper/de…...

mac m4 Homebrew安装MySQL 8.0

1.使用Homebrew安装MySQL8 在终端中输入以下命令来安装MySQL8&#xff1a; brew install mysql8.0 安装完成后&#xff0c;您可以通过以下命令来验证MySQL是否已成功安装&#xff1a; 2.配置mysql环境变量 find / -name mysql 2>/dev/null #找到mysql的安装位置 cd /op…...

Java关于多态

多态 字面意思&#xff1a;对象的多种形态。 Student(子类)<-Person(父类)->Teacher(子类) Student snew Student(); 学生形态 对象 代表用new创建一个学生对象赋值给Student 类型&#xff0c;代表Student类型(学生对象)现在是学生形态。 有了多态之后&#xff…...

K8S学习之基础四十六:k8s中部署Kibana

部署kibana组件 上传kibina镜像到harbor 部署kibana组件&#xff0c;包括svc和deplomentvi kibana.yaml apiVersion: v1 kind: Service metadata:name: kibananamespace: kube-logginglabels:app: kibana spec:ports:- port: 5601selector:app: kibana --- apiVersion: apps/…...

如何快速对比两个不同的excel文件中的单元格的数据是否完全相同 并把不同的单元格的背景颜色更改为红色?

要快速对比两个不同的Excel文件中的单元格数据是否完全相同&#xff0c;并将不同的单元格背景颜色更改为红色&#xff0c;可以使用Excel的以下几种方法&#xff1a; 方法一&#xff1a;使用条件格式 打开两个Excel文件。将一个文件的内容复制到另一个文件的新工作表中&#x…...

基于Python+LanceDB实战向量搜索

本篇实战演示向量搜索的实现和示例。 预期效果 给出一个查询的字符串&#xff0c;通过向量搜索&#xff0c;在下面三个语句中搜索出关联性最大的那句。 "熊猫是中国的国宝&#xff0c;主要栖息在四川山区。","长城是古代中国建造的军事防御工事&#xff0c;全…...

多路转接epoll

目录 一、为什么epoll最高效&#xff1f; 二、epoll的三个系统调用 三、理解epoll模型 四、epoll的优点 五、epoll的使用示例 六、epoll的工作模式 ET模式和LT模式的对比 七、epoll的使用场景 总结 一、为什么epoll最高效&#xff1f; 按照 man 手册的…...

AI编程工具哪家强?对比Cusor、Copilot、Cline

前言 AI最先革谁的命&#xff1f;刚毕业参加工作的那个时候就在想是否可以开发一个程序让它自己写代码&#xff0c;在那个遥远的年代&#xff0c;这种想法仿佛就是天方夜谭。但是今天大模型的出现让理想成为了现实。回答前面的问题&#xff0c;AI最先革谁的命&#xff0c;最聪…...

[FPGA基础学习]实现流水灯与按键暂停

FPGA实现LED流水灯 1.vscode的安装和使用 vscode下载 Visual Studio Code - Code Editing. Redefined vscode插件&#xff08;Verilog-HDL/SystemVerilog&#xff09;下载 quartus绑定vscode 2.用6个LED完成周期为1秒的跑马灯效果 流水灯模块设计 时钟输入 DE2-115开发板…...

刷题记录(LeetCode 994.腐烂的橘子)

在给定的 m x n 网格 grid 中&#xff0c;每个单元格可以有以下三个值之一&#xff1a; 值 0 代表空单元格&#xff1b;值 1 代表新鲜橘子&#xff1b;值 2 代表腐烂的橘子。 每分钟&#xff0c;腐烂的橘子 周围 4 个方向上相邻 的新鲜橘子都会腐烂。 返回 直到单元格中没有…...

ECharts折线图源码合集1(共18个自定义图表),附视频讲解与代码下载

引言&#xff1a; 在数据可视化的世界里&#xff0c;ECharts凭借其丰富的图表类型和强大的配置能力&#xff0c;成为了众多开发者的首选。今天&#xff0c;我整理了18个自定义折线图图表&#xff0c;不仅对每个图表代码进行了精简优化&#xff0c;剥离冗余配置项&#xff0c;…...

SQL小菜之TOP N查找问题

前言 SQL的编写是后端面试中非常常见&#xff0c;其中TOP N查找问题也是高频出现的问题&#xff0c;今天我们来看两道SQL TOPN问题。 问题 我们有一张雇员表Employee&#xff1a; CREATE TABLE Employee (id int DEFAULT NULL,salary int DEFAULT NULL,department varchar(…...

蓝桥杯 临时抱佛脚 之 二分答案法与相关题目

二分答案法&#xff08;利用二分法查找区间的左右端点&#xff09; &#xff08;1&#xff09;估计 最终答案可能得范围 是什么 &#xff08;2&#xff09;分析 问题的答案 和 给定条件 之间的单调性&#xff0c;大部分时候只需要用到 自然智慧 &#xff08;3&#xff09;建…...

Css环形旋转立体感动画

Css环形旋转立体感动画 index.html <!DOCTYPE html> <html lang"en" > <head><meta charset"UTF-8"><title>Css环形旋转立体感动画</title><link rel"stylesheet" href"./style.css">&l…...

音乐极客指南:Melody高音质私有云音乐平台本地部署方案

文章目录 前言1. 添加镜像源2. 本地部署Melody3. 本地访问与使用演示4. 安装内网穿透5. 配置Melody公网地址6. 配置固定公网地址 前言 嘿&#xff0c;各位音乐爱好者们&#xff01;今天我要带大家玩个大招——在香橙派Zero3上搭建你的专属在线音乐平台&#xff0c;还能通过cpo…...

Microi吾码界面设计引擎之基础组件用法大全【内置组件篇·中】

&#x1f380;&#x1f380;&#x1f380; microi-pageengine 界面引擎系列 &#x1f380;&#x1f380;&#x1f380; 一、Microi吾码&#xff1a;一款高效、灵活的低代码开发开源框架【低代码框架】 二、Vue3项目快速集成界面引擎 三、Vue3 界面设计插件 microi-pageengine …...

# WebSocket 与 Socket.IO 对比与优化

核心概念对比 WebSocket 协议性质&#xff1a;HTML5 提供的全双工通信协议 (RFC 6455)连接方式&#xff1a;基于 TCP 的低层协议通信模式&#xff1a;持久化连接&#xff0c;服务端可主动推送协议升级&#xff1a;通过 HTTP 101 状态码切换协议 Socket.IO 协议性质&#xf…...

vue3中,route4,获取当前页面路由的问题

首先应用场景如下&#xff1a; 在main.js里面&#xff0c;引入的是路由的配置文件&#xff0c;如下&#xff1a; import {router} from /router; app.use(router); 路由配置文件router.js如下&#xff1a; import { createRouter, createWebHistory } from vue-router; imp…...

python将整个txt文件写入excel的一个单元格?

要将整个txt文件写入Excel的一个单元格&#xff0c;可以使用Python的openpyxl库来实现。以下是一个简单的示例代码&#xff1a; from openpyxl import Workbook# 读取txt文件内容 with open(file.txt, r) as file:txt_content file.read()# 创建一个新的Excel工作簿 wb Work…...

日志2333

Pss-9 这一关考察的是时间盲注 先练习几个常见命令语句&#xff1a; select sleep(5);--延迟5s输出结果 if &#xff08;1>0,ture,false&#xff09;;--输出‘ture’ /if &#xff08;1<0,ture,false&#xff09;;--输出‘false’ select ascii()/select ord()返回字…...

用Deepseek写扫雷uniapp小游戏

扫雷作为Windows系统自带的经典小游戏&#xff0c;承载了许多人的童年回忆。本文将详细介绍如何使用Uniapp框架从零开始实现一个完整的扫雷游戏&#xff0c;包含核心算法、交互设计和状态管理。无论你是Uniapp初学者还是有一定经验的开发者&#xff0c;都能从本文中获得启发。 …...

C++中的异常和智能指针

一、C中的异常 1.1C语言中关于错误的处理&#xff08;回顾&#xff09; 1.1.1处理一&#xff1a;文件中的错误码&#xff0c;错误信息 C语言中&#xff0c;文件打开成功则返回地址&#xff0c;不成功返回0 FILE* foutfopen("Test.txt","r"); cout<&…...

Selenium 简单入门操作示例

最简单的 Selenium 示例&#xff08;Python版&#xff09; 下面是一个完整的、最简单的 Selenium 操作示例&#xff0c;带你快速上手&#xff1a; from selenium import webdriver from selenium.webdriver.common.by import By import time# 1. 启动浏览器&#xff08;这里使…...

6.1 模拟专题:LeetCode 1576. 替换所有的问号

1. 题目链接 LeetCode 1576. 替换所有的问号 2. 题目描述 给定一个仅包含小写字母和问号 ? 的字符串 s&#xff0c;要求将所有 ? 替换为任意小写字母&#xff0c;使得替换后的字符串中 没有相邻的两个字符相同。 示例&#xff1a; 输入&#xff1a;s "?zs" →…...

前端知识点---用正则表达式判断邮箱(javascript)

// 全面的正则&#xff08;兼容大多数情况&#xff09; const emailRegex /^[a-zA-Z0-9._%-][a-zA-Z0-9.-]\.[a-zA-Z]{2,}$/;// 或直接使用浏览器内置验证 <input type"email" required>/&#xff1a;正则表达式的起始和结束标志。 ^&#xff1a;匹配字符串的…...

深度剖析 Spring 源码 性能优化:核心原理与最佳实践

深度剖析 Spring 源码 & 性能优化&#xff1a;核心原理与最佳实践 &#x1f680; Spring 框架 作为 Java 生态的核心技术&#xff0c;广泛应用于企业级开发。但很多开发者只会“用”Spring&#xff0c;而不深入其内部原理&#xff0c;导致无法高效排查问题 & 进行性能优…...

Axure RP9教程 :轮播图(动态面板) | 头部锁定

文章目录 引言I 轮播图操作步骤在画布中添加一个动态面板设置面板状态II 头部锁定将头部区域选中,右键组合或用Ctrl+G快捷键;将组合的头部区域,右键创建动态面板;引言 动态面板的功能十分强大,比如:拥有独立的内部坐标系,有多个状态; Banner的案例中会用到动态面板多个…...

rabbitmq承接MES客户端服务器

文章目录 背景整体架构概述方案详细步骤1. 数据库选型与搭建2. 设备端数据上传至数据库3. 搭建 RabbitMQ 服务器4. 数据同步模块&#xff08;数据库到 RabbitMQ&#xff09;5. MES 服务器从 RabbitMQ 接收数据6. 指令接收模块&#xff08;RabbitMQ 到设备端&#xff09; 7. MES…...

重学vue3(三):vue3基本语法及使用

组合式 API是vue3 的核心特性&#xff0c;替代 Vue2 的选项式 API&#xff0c;强调逻辑复用和代码组织。基本语法如下&#xff1a; <script setup> import { ref, reactive, computed, onMounted } from vue;// 1. 响应式数据 const count ref(0); // 基本类…...

算法 | 麻雀搜索算法原理,公式,改进算法综述,应用场景及matlab完整代码

一、麻雀搜索算法(SSA)原理 1. 算法基础 麻雀搜索算法(Sparrow Search Algorithm, SSA)是2020年提出的一种群体智能优化算法,灵感来源于麻雀群体的觅食与反捕食行为。算法将麻雀分为三类角色:发现者(Producer):适应度最高,负责探索全局最优区域;加入者(Follower)…...

0322-数据库与前后端的连接、数据库表的增删改查

前端 <!DOCTYPE html> <html> <head> <meta charset"UTF-8"> <title>Insert title here</title> <script srcjs/jquery-3.7.1.min.js></script> <script> //jquaryajax发起请求 //传参形式不同 post用data{}…...

详细介绍Qt中用于断言的宏 Q_ASSERT

Q_ASSERT 是 Qt 框架中用于调试的核心宏之一&#xff0c;其作用类似于标准 C/C 的 assert&#xff0c;但针对 Qt 的特性进行了优化。它用于在开发阶段验证程序的逻辑正确性&#xff0c;帮助开发者快速定位潜在的错误。 1.基本用法 Q_ASSERT(condition);功能&#xff1a;在调试…...

基于Python的自然语言处理系列(60):使用 LangChain 构建 Multi-Vector Retriever 进行文档检索

在 NLP 和 AI 领域&#xff0c;基于嵌入&#xff08;Embeddings&#xff09;进行文档检索已成为一种高效的解决方案。本文介绍如何使用 LangChain 构建 Multi-Vector Retriever&#xff0c;实现对长文档的分块索引和高效检索。 1. 环境准备 首先&#xff0c;我们需要安装相关…...

Dify 部署指南-离线版

Docker 部署 1、 访问 Docker 官网 (https://www.docker.com/) 获取安装包。 2、 上传 Docker 安装包 3、 进入解压目录&#xff0c;执行解压命令 tar xzvf docker-28、0.2、tgz4、 将解压文件中的 Docker 相关文件移动到 /usr/bin/ 目录 sudo cp docker/* /usr/bin/5、 创建…...