动手学深度学习---线性神经网络
一、线性回归
解析解:模型的解可以用一个公式简单的表示,这类解叫做解析解。
超参数:可以调整但不在训练过程中更新的参数称为超参数。调参是选择超参数的过程。超参数通常是我们根据训练迭代结果来调整的。
在无法得到解析解的情况下,我们也可以有效训练模型。用到一种称为梯度下降的方法,这种方法几乎可以优化所有的深度学习模型。它通过不断地在损失函数递减的方向上更新参数来降低误差。
梯度下降的最简单的用法是计算损失函数(数据集中所有样本的损失均值)关于模型参数的导数(梯度)。在实际中可能比较慢,因为在每次更新参数之前,我们必须遍历整个数据集。因此,我们通常会在每次需要计算更新的时候随机抽取一小批样本,这种变体叫做小批量随机梯度下降。
1.1 线性回归从零开始实现
通过代码从零开始实现线性回归整个方法,包括数据流水线、模型、损失函数和小批量随机梯度下降优化器。从零开始实现可以确保我们真正知道自己在做什么,同时,了解更细致的工作原理将方便我们自定义模型、自定义层或自定义损失函数。
1.1.1 生成数据集
根据带有噪声的线性模型构造一个数据集,任务是使用这个有限样本的数据集来恢复这个模型的参数。生成一个包含1000个样本的数据集,每个样本包含从标准正态分布中抽样的两个特征。合成的数据集是一个1000个2维的矩阵。
使用线性模型参数w=[2,-3.4],b=4.2和噪声项 𝝴 来生成数据集及其标签:y=wX+b+𝝴,𝝴 可以视为模型预测和标签的潜在观测误差。假设 𝝴 服从均值为0的正态分布。
import torch
from d2l import torch as d2l
def synthetic_data(w,b,num_examples):"""生成y=wx+b+噪声"""X = torch.normal(0, 1, (num_examples, len(w))) # 生成特征矩阵y = torch.matmul(X, w) + b # 计算 X 和 w 的矩阵乘法y+= torch.normal(0,0.01,y.shape) # 为标签添加随机噪声return X,y.reshape((-1,1)) # 返回特征和标签,并将标签重塑为列向量
true_w=torch.tensor([2,-3.4])
true_b=4.2
features,labels=synthetic_data(true_w,true_b,1000)
print('features:',features[0],'\nlabel:',labels[0])
注意:features的中的每一行都包含一个二维数据样本,labels中的每一行都包含一维标签值(一个标量)。通过生成第二个特征features[:,1]和 labels 的散点图,可以直观地观察到两者之间的线性关系。
d2l.set_figsize(figsize=(8,4)) #设置图形的尺寸
d2l.plt.scatter(features[:, (1)].detach().numpy(), labels.detach().numpy(), 1) #选择 features 矩阵中的第二列
#detach() 用于从计算图中分离出该张量,这意味着此操作后,features[:, (1)] 和 labels 将不会再参与梯度计算。将PyTorch 张量转换为 NumPy 数组
1.1.2 读取数据
训练模型时要对数据集进行遍历,每次抽取小批量样本,并使用它们来更新我们的模型,由于这个过程是训练机器学习算法的基础,因此有必要定义一个函数,该函数能打乱数据集中的样本并以小批量方式获取数据。
import random
def data_iter(batch_size,features,labels): #实现了一个数据迭代器 data_iter,用于按批次生成数据num_examples=len(features)indices=list(range(num_examples))random.shuffle(indices)for i in range(0,num_examples,batch_size):batch_indices=torch.tensor(indices[i:min(i+batch_size,num_examples)])yield features[batch_indices],labels[batch_indices#这是一个生成器函数,意味着函数在调用时会返回一个批次的数据,之后可以继续从当前位置继续执行。这使得 data_iter 可以按需生成批次,而不是一次性加载所有数据到内存。
读取第一个小批量数据样本并打印,每个批量的特征维度显示批量大小和输入特征数。同样,批量的标签形状与batch_size相等。
batch_size=10
for X,y in data_iter(batch_size,features,labels):print(X,y)break
当我们执行迭代时,会连续地获得不同的小批量,直至遍历完整个数据集。
1.1.3 初始化模型参数
在我们开始用小批量随机梯度下降优化我们的模型参数之前,我们需要先有一些参数。通过从均值为0,标准差为0.01的正态分布中抽样随机数来初始化权重,并将偏置初始化为0。
w=torch.normal(0,0.01,size=(2,1),requires_grad=True)
b=torch.zeros(1,requires_grad=True)
在初始化参数之后,我们的任务是更新这些参数,直到这些参数足以拟合我们的数据。每次更新都需要计算损失函数关于模型参数的梯度。有了这个梯度,我们就可以向减小损失的方向更新每个参数。可以通过自动微分来计算梯度。
1.1.4 定义模型
接下来,需要定义模型,将模型的输入和参数同模型的输出关联起来。
def linreg(X,w,b):"""线性回归模型"""return torch.matmul(X,w)+b
1.1.5 定义损失函数
因为需要计算损失函数的梯度,所以应该先定义损失函数。
def squared_loss(y_hat,y):"""均方损失"""return (y_hat-y.reshape(y_hat.shape))**2/2
1.1.6 定义优化算法
在每一步中,使用从数据集中随机抽取的一个小批量,然后根据参数计算损失的梯度。接下来,朝着减少损失的方向更新我们的参数。下面的函数实现小批量随机梯度下降更新。该函数接收模型参数集合、学习率和批量大小作为输入。每一步更新的大小由学习率lr决定。
def sgd(params,lr,batch_size): #params一个列表或迭代器,包含了模型的所有需要优化的参数,学习率(learning rate)"""小批量随机梯度下降"""with torch.no_grad(): #上下文管理器用于指示 PyTorch 在执行其中的操作时不需要计算梯度。for param in params:param-=lr*param.grad/batch_size #param.grad 获取当前参数的梯度 #因为在小批量随机梯度下降中,根据批次样本的平均梯度来更新参数,所以这里需要除以batch_size来平均每个样本对参数更新的贡献。param.grad.zero_() #清空当前参数的梯度
1.1.7 训练
在每次迭代中,读取小批量训练样本,并通过模型来获得一组预测。计算完损失后,开始反向传播,存储每个参数的梯度。最后,调用优化算法 sgd 来更新模型参数。
#训练过程
lr=0.03
num_epochs=10
net=linreg
squared_loss=squared_loss
for epoch in range(num_epochs):for X,y in data_iter(batch_size,features,labels):l=squared_loss(net(X,w,b),y)l.sum().backward()sgd([w,b],lr,batch_size)with torch.no_grad():train_l=squared_loss(net(features,w,b),labels)print(f'epoch{epoch+1},loss{float(train_l.mean())}')
使用的是自己合成的数据集,知道真实参数是什么,因此,可以通过比较真实参数和通过训练学习的参数来评估训练的成功程度。事实上,从估计误差结果可以看出真实参数和通过训练学习的参数确实非常接近。
print(f'w的估计误差:{true_w-w.reshape(true_w.shape)}')
print(f'b的估计误差:{true_b-b}')
1.2 线性回归的简洁实现
1.2.1 生成数据集
import pandas as pd
import torch
from torch.utils import data
from d2l import torch as d2ltrue_w=torch.tensor([2,-3.4])
true_b=4.2
def synthetic_data(w,b,num_examples):"""生成y=wx+b+噪声"""X = torch.normal(0, 1, (num_examples, len(w)))y = torch.matmul(X, w) + by+= torch.normal(0,0.01,y.shape)return X,y.reshape((-1,1))
features,labels=synthetic_data(true_w,true_b,1000)
1.2.2 读取数据
可以通过调用框架中现有的API来读取数据,将 features 和 labels 作为API的参数传递,并通过数据迭代器指定batch_size。此外,布尔值is_train表示是否希望数据迭代器对象在每轮内打乱数据。
def load_array(data_arrays,batch_size,is_train=True):"""构造pytorch 数据迭代器"""dataset=data.TensorDataset(*data_arrays)#它将输入的特征和标签(通过 *data_arrays 解包传递)打包成一个数据集对象。return data.DataLoader(dataset,batch_size,shuffle=is_train)
#data_arrays是一个包含数据的元组,通常是两个元素:一个是特征(X),另一个是标签(y)。数据会被封装成PyTorch的TensorDataset,供后续的 DataLoader使用。
#函数最终返回的是一个 DataLoader 对象,允许我们以小批量的形式迭代数据。
batch_size=10
data_iter=load_array((features,labels),batch_size)
next(iter(data_iter))
1.2.3 定义模型
对于标准深度学习模型,可以使用框架的预定义好的层。这使我们只需关注使用哪些层来构造模型,而不必关注层的实现细节。我们先定义一个模型变量net,它是一个Sequential类的实例。Sequential类将多个层串联在一起。当给定输入数据时,Sequential实例将数据传入第一层,然后将第一层的输出作为第二层的输入,以此类推。
在Pytorch中,全连接层在Linear类中定义,将两个参数传递到nn.Linear中。第一个参数指定输入特征形状,即2.第二个参数指定输出特征形状,输出特征形状为单个标量,因此为1.
from torch import nn
net=nn.Sequential(nn.Linear(2,1))
1.2.4 初始化模型参数
在使用net之前,需要初始化模型参数,如在线性回归模型中的权重和偏置。深度学习框架通常由预定义的方法来初始化参数。在这里,指定每个权重参数应该从均值为0,标准差为0.01的正态分布中随机抽样,偏置参数初始化为零。通过net[0]选择网络中第一层,然后使用weight.data和bias.data方法访问参数。还可以使用替换方法normal_和fill_来重写参数值。
net[0].weight.data.normal_(0,0.01)
net[0].bias.data.fill_(0)
1.2.5 定义损失函数
计算均方误差使用的是MSELoss类,其也称为平方L2范数。默认情况下,它返回所有样本损失的平均值。
loss=nn.MSELoss()
1.2.6 定义优化算法
小批量随机梯度下降算法是一种优化神经网络的标准工具,Pytorch在optim模块中实现了该算法的许多变体。实例化一个SGD实例时,需要指定优化的参数(可通过net.parameters()从模型中获得)以及优化算法所需的超参数字典。小批量随机梯度下降只需要设置lr的值,这里设置为0.03。
trainer=torch.optim.SGD(net.parameters(),lr=0.03)
1.2.7 训练
通过深度学习框架的高级API来实现模型只需要相对较少的代码,不必单独分配参数,不必定义损失函数,也不必手动实现小批量随机梯度下降。使用更复杂的模型时,高级API的优势将极大显现。有了所有的基本组件,训练过程的代码与从零开始实现时的非常相似。
回顾一下,在每轮里,将完整遍历一次数据,不断地从中获取一个小批量的输入和相应的标签。对于每个小批量,我们会执行以下步骤。
- 通过调用net(x)生成预测并计算损失L(前向传播)
- 通过反向传播来计算梯度
- 通过调用优化器来更新模型参数
为了更好地度量训练效果,我们计算每轮后的损失,并打印处理监控训练过程
num_epochs=10
for epoch in range(num_epochs):for X,y in train_iter:l=loss(net(X),y) #表示模型的前向传播过程,它返回预测的输出trainer.zero_grad() #在进行反向传播之前清空上一轮计算的梯度l.backward()trainer.step() #通过优化器更新模型的参数,优化器会使用前一步计算的梯度来调整参数,以减小损失l=loss(net(features),labels)print(f'epoch{epoch+1},loss{l:.4f}') #f:普通浮动点数格式;.4f保留四位小数
比较生成数据集的真实参数和通过有限数据训练获得的模型参数。要访问参数,首先从net访问所需的层,然后读取该层的权重和偏置。
w=net[0].weight.data
print('w的估计误差:',true_w-w.reshape(true_w.shape))
b=net[0].bias.data
print('b的估计误差:',true_b-b)
二、softmax回归
通常,机器学习实践者用分类这个词来描述两个有微妙差别的问题:(1)如果我们只对样本的“硬性”类别感兴趣,就属于某个类别;(2)如果我们希望得到“软性”类别,就属于某个类别的概率。这两者的界限往往很模糊,其中的一个原因是:即使我们只关心硬性类别,我们也仍然使用软性类别的模型。
与线性回归一样,softmax回归也是一个单层神经网络,输出层也是全连接层。softmax运算不会改变未规范化的预测值之间的大小次序,只会确定分配给每个类别的概率。
2.1 图像分类数据集
2.1.1 读取数据
MINIST数据集是图像分类中广泛使用的数据集之一,但作为基准数据集过于简单。此次使用类似但复杂的Fashion-MINIST数据集。通过框架中的内置函数将Fashion-MINIST数据集下载并读取到内存中。
%matplotlib inline
import torch
import torchvision
from torch.utils import data
import torchvision.transforms as transforms
from d2l import torch as d2l
import numpy as npd2l.use_svg_display()
trans = transforms.ToTensor() #通过ToTensor实例将图像数据从PIL类型变换成32位浮点数形式,并除以255使得所有像素的数值均为0~1
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)
Fashion-MINIST 由10个类别的图像组成,每个类别由训练数据集中的6000张图像和测试数据集中的1000张图像组成。因此,训练集和测试集分别包含6000和1000张图像。测试数据集不会用于训练,只用于评估模型性能。
len(mnist_train), len(mnist_test) #(60000, 10000)
每个输入图像的高度和宽度均为28像素。数据集由灰度图像组成,其通道数为1,为简洁起见,将高度为h像素,宽度为w像素的图像的形状记为(h,w)或 hxw
mnist_train[0][0].shape #torch.Size([1, 28, 28])
Fashion-MINIST中包含的10个类别分别为T-shirt(T恤)、trouser(裤子)、pullover(套衫)、dress(连衣裙)、coat(外套)、sandal(凉鞋)、shirt(衬衫)、sneaker(运动鞋)、bag(包)和ankle boot(短靴)。
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: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))
2.1.2 读取小批量数据
为了使读取训练集和测试集时更容易,使用内置的数据迭代器,而不是从零开始创建。在每次迭代中,数据加载器都会读取一小批量数据,大小为batch_size。通过内置的数据迭代器,可以随机打乱所有样本,从而无偏见的读取小批量数据。
batch_size = 256
train_iter = data.DataLoader(mnist_train, batch_size, shuffle=True, num_workers=4) #使用4个进程来读取数据
#读取数据所需时间
timer=d2l.Timer()
for X, y in train_iter:continue
print(f'{timer.stop():.2f} sec')
2.1.3 整合所有组件
定义load_data_fashion_mnist函数,用户获取和读取Fashion-MINIST数据集,这个函数返回训练集和验证集的数据迭代器。实现了加载并处理 FashionMNIST 数据集的功能。此外,这个函数还接收一个可选参数resize,用来将图像调整为另一种形状。
def load_data_fashion_mnist(batch_size, resize=None): #通过resize参数来测试load_data_fashion_mnist函数图像大小调整功能。trans = [transforms.ToTensor()] #创建列表,ToTensor()是一个图像转换函数,将图像从PIL格式或numpy数组转换为tensor格式。if resize:trans.insert(0, transforms.Resize(resize))trans = transforms.Compose(trans) #transforms.Compose() 是一个容器,可以将多个图像转换操作组合成一个流水线。mnist_train = torchvision.datasets.FashionMNIST(root="../data", train=True, transform=trans, download=False)mnist_test = torchvision.datasets.FashionMNIST(root="../data", train=False, transform=trans, download=False)return (data.DataLoader(mnist_train, batch_size, shuffle=True, num_workers=4),data.DataLoader(mnist_test, batch_size, shuffle=False, num_workers=4))
train_iter, test_iter = load_data_fashion_mnist(32, resize=64)
for X, y in train_iter:print(X.shape, X.dtype, y.shape, y.dtype) #X.shape:32 是批量大小,1 是通道数,64x64 是图像的大小break
2.2 softmax 回归从零开始实现
原始数据集中的每个样本都是28像素x28像素。展平每张图像,把它们看作长度为784的向量。输出与类别一样多,因为数据集有10个类别,所以网络输出维度为10,因此,权重将构建一个784x10的矩阵,偏置将构成一个1x10的行向量。使用正态分布初始化权重w,偏置初始化为0。
2.2.1 初始化模型参数
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)
2.2.2 定义softmax 操作
实现softmax由以下3个步骤组成:
(1)对每个项求幂(使用exp)
(2)对每一行求和(同一列轴0,同一行轴1,小批量中的每个样本是一行),得到每个样本的规范化参数
(3)将每一行除以其规范化常数,确保结果的和为1
def softmax(X):X_exp = torch.exp(X)partition = X_exp.sum(1, keepdim=True) #同一列轴0,同一行轴1 keepdim=True:保持维度return X_exp / partition
#测试数据样例
X=torch.normal(0, 1, (2, 5))
X_prob = softmax(X)
X,X_prob,X_prob.sum(1)
2.2.3 定义模型
def net(X):return softmax(torch.matmul(X.reshape((-1, W.shape[0])), W) + b)
2.2.4 定义损失函数
计算交叉熵损失函数。
def cross_entropy(y_hat, y):return - torch.log(y_hat[range(len(y_hat)), y])
2.2.5 分类精度
当预测与分类标签y一致时是正确的。分类精度是正确预测数与预测总数之比。为了计算精度,首先,如果y_hat是矩阵,那么假定第二个维度存储每个类别的预测分数,使用argmax获得每行中最大元素的索引来获得预测类别,然后,将预测类别与真实y元素进行比较。由于等式运算符“==”对数据类型很敏感,因此将y_hat的数据类型转换为与y的数据类型一致。结果是一个包含0(错)和1(对)的张量。最后,我们求和会得到预测正确的数量。
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())def evaluate_accuracy(data_iter, net):if isinstance(net, torch.nn.Module):net.eval() # 将模型设置为评估模式metric = d2l.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实例创建了两个变量,分别用于存储正确预测数和预测总数。当我们遍历数据集时,两者都将随着时间的推移而累加。
class Accumulator:"""在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]
由于使用随机权重初始化net模型,因此该模型的精度应接近于随机猜测。在有10个类别情况下的精度接近0.1
evaluate_accuracy(test_iter, net) #输出:0.1047
2.2.6 训练
def train_epoch_ch3(net, train_iter, loss, updater):if isinstance(net, torch.nn.Module): # 是否是pytorch的nn.Modulenet.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]
在展示训练函数之前,定义一个在动画中绘制图表的实用程序类 Animator,它能简化其余部分代码。
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.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, 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)
接下来实现一个训练函数,它会在train_iter 访问的训练数据集上训练一个模型net,该训练函数将会运行多轮(由num_epochs指定),在每轮结束时,利用test_iter访问的测试数据集对模型进行评估。
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(test_iter, net)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.1
def updater(batch_size):return d2l.sgd([W, b], lr, batch_size)
num_epochs=10 #训练模型10轮。
train_ch3(net, train_iter, test_iter, cross_entropy, num_epochs, updater)
2.2.7 预测
def predict_ch3(net, test_iter, n=6):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)
2.3 softmax回归简洁实现
2.3.1 初始化模型参数
import torch
from torch import nn
from d2l import torch as d2l
batch_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)
2.3.2 定义损失函数
loss = nn.CrossEntropyLoss()
2.3.3 优化算法
使用学习率为0.1的小批量随机梯度下降作为优化算法。
trainer = torch.optim.SGD(net.parameters(), lr=0.1)
2.3.4 训练
num_epochs = 10
d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, trainer)
相关文章:
动手学深度学习---线性神经网络
一、线性回归 解析解:模型的解可以用一个公式简单的表示,这类解叫做解析解。 超参数:可以调整但不在训练过程中更新的参数称为超参数。调参是选择超参数的过程。超参数通常是我们根据训练迭代结果来调整的。 在无法得到解析解的情况下…...
24计算机考研,东南大学和电子科技大学如何选择?
针对题主的情况,更推荐成电。成电上岸更为简单,就业前景也非常不错,性价比相当高。如果基础很扎实、更注重学校牌子、或是未来想在江浙沪发展的同学,东南大学是个很好的选择。下面就从学校综合实力、招录情况、考试难度来详细对比…...
Redis应用-在用户数据里的应用
1.社区电商的业务闭环 接下来介绍的社区电商是以Redis作为主体技术、以MySQL和RocketMQ作为辅助技术实现的。 (1)社区电商运作模式 社区电商的关键点在于社区,而电商则是辅助性质(次要地位,流量变现)。社区可以分成很多种社区,比如美食社区、美妆社区、影评社区、妈妈社区…...
STL容器-map P3613【深基15.例2】寄包柜 普及-
题目来源:洛谷题库 文章目录 map例题map知识点map使用注意:map的常用用法 map例题 P3613【深基15.例2】寄包柜 普及- 题意 根据数据插入/查询 思路 map键值对可以根据柜子编号查找物品,但是柜子又有很多个,考虑数组或者map数组…...
excel使用笔记
1.工作表1计算工作表2某列的和 假设我们有两个工作表,分别命名为“Sheet1”和“Sheet2”,我们想要求和这两个工作表中A1到A**单元格的数据,可以在任意一个工作表的单元格中输入以下公式: SUM(Sheet1!A1:A10, Sheet2!A1:A10) SUM…...
EasyGBS点对点穿透P2P远程访问技术在安防视频监控中的应用
随着信息技术的快速发展,安防视频监控系统在公共安全领域的应用变得越来越广泛。传统的视频监控系统多依赖于中心服务器进行视频流的集中处理和分发,这不仅增加了网络带宽的负担,还可能成为系统性能瓶颈。为了解决这些问题,P2P&am…...
【MySQL中多表查询和函数】
目录 1.多表查询 1.1 外键 1.2 链接查询 2.MySQL函数 内置函数简介 数值函数 字符串函数 时间日期函数 条件判断操作 开窗函数 1.多表查询 本质:把多个表通过主外键关联关系链接(join)合并成一个大表,在去单表查询操作…...
Polars数据聚合与旋转实战教程
在这篇博文中,我们的目标是解决数据爱好者提出的一个常见问题:如何有效地从Polars DataFrame中创建汇总视图,以便在不同时间段或类别之间轻松进行比较。我们将使用一个实际的数据集示例来探索实现这一目标的各种方法。 Polars简介 Polars 是…...
SpringBoot【十三(准备篇)】集成在线接口文档Swagger2
一、前言🔥 环境说明:Windows10 Idea2021.3.2 Jdk1.8 SpringBoot 2.3.1.RELEASE 二、swagger介绍 我就不卖关子啦,相信在座的各位很多都已经用过,但是没关系,只要全世界还有一个没用过,我都会给他讲。 那…...
CKA认证 | Day6 K8s网络
第六章 Kubernetes网络 1、Service 控制器 在 Kubernetes (K8S) 中,Service 控制器 是一个关键组件,负责管理 Kubernetes 服务的生命周期和实现其功能。Service 控制器确保服务能够正确地将流量路由到后端 Pod,并处理服务的负载均衡和 DNS …...
基于Llamaindex的网页内容爬取实战
目的 本文不关注如何解析网页 html 元素和各种 python 爬虫技术,仅作为一种网页数据的预处理手段进行研究。Llamaindex 也并不是爬虫技术的集大成者,使用它是为了后续的存查一体化。 安装依赖 pip install llama-index-readers-web # pip install llam…...
springboot429校运会管理系统(论文+源码)_kaic
摘 要 传统办法管理信息首先需要花费的时间比较多,其次数据出错率比较高,而且对错误的数据进行更改也比较困难,最后,检索数据费事费力。因此,在计算机上安装校运会管理系统软件来发挥其高效地信息处理的作用ÿ…...
tcpdump编译
https://github.com/westes/flex/releases/download/v2.6.4/flex-2.6.4.tar.gz tar -zxvf flex-2.6.4.tar.gz ./configure CFLAGS-D_GNU_SOURCE make sudo make installwget http://ftp.gnu.org/gnu/bison/bison-3.2.1.tar.gz ./configure make sudo make install以上两个库是…...
Vite快速构建Vue教程
步骤 1: 初始化项目目录 创建一个名为 projects 的文件夹,作为存放所有 Vite 项目的根目录。这个文件夹将容纳多个独立的 Vite 项目。 步骤 2: 创建 Vite 项目 右键点击 projects 文件夹并选择“在此处打开终端”或使用您偏好的代码编辑器(如 VSCode&…...
四、个人项目系统搭建
文章目录 一、python写的后端代码二、html代码三、index.css四、js代码 效果图: 一、python写的后端代码 后端代码使用Flask编写,如下所示: # app.py from flask import Flask, render_template, request, jsonify, g import sqlite3 import…...
长沙理工大学《2024年825自动控制原理真题》 (完整版)
本文内容,全部选自自动化考研联盟的:《长沙理工大学825自控考研资料》的真题篇。后续会持续更新更多学校,更多年份的真题,记得关注哦~ 目录 2024年真题 Part1:2024年完整版真题 2024年真题...
Linux上安装Anaconda
查看版本 lsb_release -a uname -m x86_64:表示系统是64位。i686、i386:表示系统是32位。 到连接安装对应版本 连接到ldhttps://repo.anaconda.com/archive/ 配置对应的conda环境,export PATH/对应目录/anaconda3/bin:$PATH *注意为bi…...
HTTP常见的请求头有哪些?都有什么作用?在 Web 应用中使用这些请求头?
HTTP 请求头(Request Headers)用于在 HTTP 请求中携带额外的信息,帮助服务器更好地处理请求。以下是一些常见的 HTTP 请求头及其作用: 常见请求头及其作用 1. Accept 作用:告知服务器客户端可以接受的内容类型。示例…...
扩展tinyplay使其自适应不同声道数量的媒体
android原来的tinyplay代码,如果遇到播放媒体的升到数量与打开pcm的声道数量不匹配的情况,会没法继续播放。 本例扩展了tinyplay的代码,将不同声道的音频数据展开/压缩到pcm设备支持的数据,再写入pcm设备。 bplay.c #include &l…...
[Unity] AppLovin Max接入Native 广告 IOS篇
NativeIOS构建流程 (接入之前备份之前打包得Xcode工程) 下载资源 1.将以下文件放入Unity Assets->Plugins->IOS文件夹下 2.Unity更新max版本至12.4.1 UnityPlugin 6.4.3以上(很重要) 3.NativeSDKManager.CS根据以下附…...
跨平台开发技术的探索:从 JavaScript 到 Flutter
随着多平台支持和用户体验一致性在应用程序开发中变得越来越重要,开发者面临的挑战是如何在不同平台上保持代码的可维护性和高效性。本文将探讨如何利用现代技术栈,包括 Flutter、JavaScript、HTML5、WebAssembly、TypeScript 和 Svelte,在统一的平台上进行高效的跨平台开发…...
计算机网络技术基础:2.计算机网络的组成
计算机网络从逻辑上可以分为两个子网:资源子网和通信子网。 一、资源子网 资源子网主要负责全网的数据处理业务,为全网用户提供各种网络资源与网络服务。资源子网由主机、终端、各种软件资源与信息资源等组成。 1)主机 主机是资源子网的主要…...
PKCS#7、Bit padding(位填充)、Byte padding(字节填充)、Zero padding(零填充)
PKCS#7、Bit padding(位填充)、Byte padding(字节填充)、Zero padding(零填充)是密码学常见的填充方式。 Bit padding(位填充): 位填充可以应用于任意长度的消息。在消息…...
在 Kibana 中为 Vega Sankey 可视化添加过滤功能
作者:来自 Elastic Tim Bosman 及 Miloš Mandić 有兴趣在 Kibana 中为 Vega 可视化添加交互式过滤器吗?了解如何利用 “kibanaAddFilter” 函数轻松创建动态且响应迅速的 Sankey 可视化。 在这篇博客中,我们将了解如何启用 Vega Sankey 可视…...
快速部署一套K8s集群-v1.28
快速部署一套K8s集群-v1.28 1.前置知识点 1.1 生产环境可部署Kubernetes集群的两种方式 目前生产部署Kubernetes集群主要有两种方式: kubeadmKubeadm是一个K8s部署工具,提供kubeadm init和kubeadm join,用于快速部署Kubernetes集群。 二进制包从github下载发行版的二进…...
python3验证有效正则表达式
Python 中字符串类型本质上没有标记“是否原始”的特性,原始字符串只是为了书写方便。运行时,原始字符串与普通字符串的表现是相同的,唯一的区别是编写代码时是否进行了转义。 因此,如果需要确保某些输入是有效正则表达式&#x…...
Dify+Xinference本地部署Embedding和Rerank模型
文章目录 1、Xinference介绍2、Xinference安装2.1 Xinference Docker安装2.2 pip安装2.3 设置开启自启动(仅针对pip安装用户) 3、部署Embedding和Rerank模型4、Dify调用Xinference模型 1、Xinference介绍 Xinference是一个性能强大且功能全面的分布…...
是时候戒掉小游戏了
玩儿这东西没够!去年本来是要备考CPA,但是赶上写毕业论文,就以此为由,没有去备考,结果论文没完成,考试也没准备,都是游戏惹的祸!今年计划备考,看了两个月书,结…...
ECMAScrip 与 ES2015(ES6):JavaScript 现代化编程的里程碑
在 JavaScript 的发展历程中,ECMASCript 和 ES2015(也称为 ES6)无疑是最具革命性的版本之一。它们不仅引入了大量的新特性和语法糖,还极大地提升了代码的可读性、可维护性和性能。本文将深入探讨 ECMASCrip 和 ES2015 的新特性及其…...
iOS swift开发系列 -- tabbar问题总结
1.单视图如何改为tabbar,以便显示2个标签页 右上角➕,输入tabbar 找到控件,然后选中,把entrypoint移动到tabbar控件 2.改成tabbar,生成两个item,配置各自视图后,启动发现报错 Thread 1: “-[p…...
nginx 部署 ModSecurity3
一、查看本地nginx版本 nginx是yum安装的 # nginx -v nginx version: nginx/1.26.2 二、安装依赖工具 # yum install -y gcc-c flex bison yajl lmdb lua curl-devel curl GeoIP-devel zlib-devel pcre-devel pcre2-devel libxml2-devel ssdeep-devel libtool autoconf aut…...
websocket_asyncio
WebSocket 和 asyncio 指南 简介 本指南涵盖了使用 Python 中的 websockets 库进行 WebSocket 编程的基础知识,以及 asyncio 在异步非阻塞 I/O 中的作用。它提供了构建高效 WebSocket 服务端和客户端的知识,以及 asyncio 的特性和优势。 1. 什么是 WebS…...
一级考试真题(2019)
一级考试真题(2019)...
OpenCV相机标定与3D重建(20)将单应性矩阵分解为旋转矩阵、平移向量和法向量函数decomposeHomographyMat()的使用
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 将单应性矩阵分解为旋转矩阵、平移向量和法向量。 cv::decomposeHomographyMat 是 OpenCV 库中的一个函数,用于将单应性矩阵…...
题解 - 取数排列
题目描述 取1到N共N个连续的数字(1≤N≤9),组成每位数不重复的所有可能的N位数,按从小到大的顺序进行编号。当输入一个编号M时,就能打印出与该编号对应的那个N位数。例如,当N=3时,可…...
LVGL9.2 鼠标悬停处理
文章目录 前言鼠标悬停处理功能简介使用场景1. **按钮悬停效果**2. **图标高亮**3. **动态工具提示** 实现原理使用方法1. 设置控件样式2. 监听悬停事件 功能亮点注意事项总结 前言 在 v9.2 版本中,新增了许多功能,其中鼠标悬停处理(Mouse H…...
每日计划-1213
1. 完成 SQL2 查询多列 https://www.nowcoder.com/exam/oj?page1tabSQL%E7%AF%87topicId199 2. 八股部分 1) C 中面向对象编程如何实现数据隐藏? 在c中,可以将数据成员声明为私有或受保护,并提供公有的成员函数来访问和修改这些数据成员&am…...
gz中生成模型
生成模型 通过服务调用生成 还记得parameter_bridge 吗? 我们在生成桥接的时候调用了这个cpp文件。 一个 parameter_bridge 实例用于消息传递(传感器数据)。之前的例子 另一个 parameter_bridge 实例用于服务桥接(动态生成模型…...
三相电机不转,如何判断好坏?
在现代工业生产中,三相电机被广泛应用于各类机械设备中,由于其高效能和稳定性,成为驱动设备的首选。然而,在实际使用过程中,三相电机有时会出现不转动的情况,这不仅会影响生产效率,还可能对设备…...
使用观测云排查数据库死锁故障
故障发现 核心应用 pod 发生重启,同时接收到对应使用者反馈业务问题,开始排查。 观测云排查现场 1、根据重启应用信息,查询 APM 执行数据库 update 操作大量报错,执行时间在 5min 以上。 分析 APM 链路异常,发现是触…...
STM32 USB通信知识与应用详解
在嵌入式系统开发中,STM32作为一款性能卓越的微控制器,其USB通信功能的应用十分广泛。本文将深入探讨STM32 USB的相关知识,从基础概念到实际应用,为读者呈现一个全面的STM32 USB通信知识体系。 一、USB基础知识 USB(…...
IoTDB 集群扩容方法
问题 问题1:当时序数据库 IoTDB 集群的存储占用达到多少时,建议增加节点?是等到存储完全满,还是达到一半时就进行扩容?如果集群存储已满,是否需要手动进行数据清理,比如设置 TTL,还…...
控制台报错:Uncaught (in promise):XXXXX问题定位以及前端文件流excel文件下载方法
今天对接上传文件的接口时,明明接口是通的,也正常返回了文件流,然而,控制台就是打印不出返回值,而且一直报错Uncaught (in promise):XXXXX 去查看axios的封装函数,这个internal error是从返回值…...
.NET平台使用C#设置Excel单元格数值格式
设置Excel单元格的数字格式是创建、修改和格式化Excel文档的关键步骤之一,它不仅确保了数据的正确表示,还能够增强数据的可读性和专业性。正确的数字格式可以帮助用户更直观地理解数值的意义,减少误解,并且对于自动化报告生成、财…...
6.2 MapReduce工作原理
MapReduce工作原理涉及将大数据集分割成小块并行处理。Map任务读取数据块并输出中间键值对,而Reduce任务则处理这些排序后的数据以生成最终结果。MapTask工作包括读取数据、应用Map函数、收集输出、内存溢出时写入磁盘以及可选的Combiner局部聚合。ReduceTask工作则…...
C语言指针
1,指针是什么 指针是内存中一个最小内存单元(一个字节)的编号,也就是地址通常口语中说的指针,通常是指指针变量也就是用来存放内存中地址的变量 每个内存单元都有一个地址,这个地址不需要存起来࿰…...
前端(async 和await)
1 async async 将 function 变为成为 async 函数 ●async 内部可以使用 await,也可以不使用,因此执行这个函数时,可以使用 then 和 catch 方法 ●async 函数的返回值是一个 Promise 对象 ●Promise 对象的结果由 async 函数执行的返回值决…...
打造高效的HIS与DAT文件解析工具
在工业数据采集和存储中,HIS 和 DAT 文件是非常常见的二进制数据格式。然而,解析这些固定块大小的二进制文件并将其转换为易读的 CSV 格式并非易事。本文将深入讲解如何使用 Python 和 PyQt5 打造一款图形化工具,轻松解析和转换这些文件&…...
YOLO系列:二、基于yolov8和labelme制作数据集及模型训练
YOLO系列:二、基于yolov8和labelme制作数据集及模型训练 1.新建一个项目1.数据集标注及类型转换1. 1 使用labelme进行数据标注1.1.1打开labelme1.1.2图像标注及存储 1. 2 将数据集转换成yolo类型 2.模型训练的配置文件2. 1打开labelme标注图像2.1.1三级目录 3.模型训…...
PHP搭建环境
一、安装apache 1、获取Apache安装软件 2、双击安装即可:指定对应的路径:E:server/apache 3、选择安装模式:使用自定义模式 4、选择安装位置 二、Apache的目录结构说明 三、Httpd.exe的详细应用 1、服务器进程:运行之后才能够工作...