多层感知机的从零实现与softmax的从零实现(真·0000零基础)

news2024/10/28 14:26:57

今天再读zh.d2l书(4.2. 多层感知机的从零开始实现 — 动手学深度学习 2.0.0 documentation),

看了关于多层感知机的从零实现与softmax的从零实现

目录

mlp从零实现,

点击“paddle”的代码

点击“torch”的代码

训练 

参数解释

   - `loss`:

参数说明:

softmax从零实现

一些工具

torch的矩阵乘法matmul

张量.numel返回张量元素数 

zip

isinstance(a,b)判断a是否是b类

 反向传播  张量.backward()

绘制动画

损失函数的定义

定义accuracy

定义精度(net模型,data_iter数据集)

定义的Accumulator(2)

定义net

定义训练函数

定义updater()

训练

使用训好的net预测 


mlp从零实现

点击“paddle”的代码

里面用到paddle库,可以方便的实现一些神经网络的东西

从paddle引入nn模块,

import warnings
from d2l import paddle as d2l

warnings.filterwarnings("ignore")
import paddle
from paddle import nn

batch_size = 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)

比如nn.linear(),可以构造线性层

nn.CrossEntropyLoss(),可以快速构造交叉熵损失函数


#初始化参数
num_inputs, num_outputs, num_hiddens = 784, 10, 256

W1 = paddle.randn([num_inputs, num_hiddens]) * 0.01
W1.stop_gradient = False
b1 = paddle.zeros([num_hiddens])
b1.stop_gradient = False
W2 = paddle.randn([num_hiddens, num_outputs]) * 0.01
W2.stop_gradient = False
b2 = paddle.zeros([num_outputs])
b2.stop_gradient = False

params = [W1, b1, W2, b2]
#损失函数
loss = nn.CrossEntropyLoss(reduction='none')

(其实是没注意点错了才发现) 

点击“torch”的代码

就是是从torch引入nn

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)

训练 

num_epochs, lr = 10, 0.1
updater = torch.optim.SGD(params, lr=lr)
d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, updater)
参数解释


1. `num_epochs`: 这个变量表示神经网络训练的轮数(或称为“纪元”)。每一轮遍历整个数据集一次就叫做一个epoch。例如,设置`num_epochs = 10`意味着网络将会被训练10次完整的迭代。
2. `lr`: 这是学习率(Learning Rate)的缩写。它决定了在每一步更新时权重更新的幅度。较小的学习率会导致更慢的收敛速度,但可能找到更好的局部最小值;较大的学习率可能会导致错过最优解或者在最优解附近震荡。这里设置了两个不同的学习率:`0.1` 和 `0.01`,可能是为了在不同阶段进行超参数调整。
3. `updater`: 这是一个函数或对象,用于执行权重的更新操作。

在这个例子中,它是通过调用`torch.optim.SGD(params, lr=lr)`创建的SGD优化器实例。

这里的`params`指的是需要优化的模型的参数集合,

num_inputs, num_outputs, num_hiddens = 784, 10, 256

W1 = nn.Parameter(torch.randn(
    num_inputs, num_hiddens, requires_grad=True) * 0.01)
b1 = nn.Parameter(torch.zeros(num_hiddens, requires_grad=True))
W2 = nn.Parameter(torch.randn(
    num_hiddens, num_outputs, requires_grad=True) * 0.01)
b2 = nn.Parameter(torch.zeros(num_outputs, requires_grad=True))

params = [W1, b1, W2, b2]

而`lr`则是之前定义的学习率。


4. `d21.train_ch3(net, train_iter, test_iter, loss, num_epochs, updater)`: 这行代码调用了某个模块(假设为`d21`)中的一个方法`train_ch3`来开始训练过程。这个方法的参数包括:
   - `net`: 需要训练的网络模型。

def net(X):
    X = X.reshape((-1, num_inputs))
    H = relu(X@W1 + b1)  # 这里“@”代表矩阵乘法
    return (H@W2 + b2)


   - `train_iter`: 训练数据的迭代器,用于逐批次地获取训练样本。
   - `test_iter`: 测试数据的迭代器,用于评估模型在未见过的数据上的性能。

这里从库里自动调的,batch size 为256 的迭代器


batch_size = 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)


   - `loss`:

用于计算损失值的函数或类,通常用来衡量预测与真实标签之间的差距。

这里从torch.nn直接取的交叉熵损失,没有传入具体参数,只是设置none

loss = nn.CrossEntropyLoss(reduction='none')
参数说明:

在PyTorch中,nn.CrossEntropyLoss是一个损失函数,用于测量分类任务的预测值与真实值之间的差距。 

  • reduction: 这个参数决定了如何处理输出损失张量。它有三个可选的值:

    • 'none': 不应用任何缩减。返回的损失与每个输入元素相对应。
    • 'mean': 返回损失的平均值。
    • 'sum': 返回所有损失的求和。

loss = nn.CrossEntropyLoss(reduction='none')reduction='none'表示损失函数会返回一个与输入同样大小的损失张量,而不是将所有损失值缩减为一个单一的数值。这意味着每个输入样本都会有一个对应的损失值,这对于需要单独处理每个样本的损失(例如在自定义的损失计算中)非常有用。

例如,如果有一个批量大小为N的输入和一个对应的标签,nn.CrossEntropyLoss(reduction='none')将会返回一个长度为N的损失张量,其中每个元素都是对应输入样本的交叉熵损失。这样, 可以根据需要进一步处理这些损失值,例如进行加权平均或者选择性地更新模型参数。

  

d2l提供的接口——

num_epochs, lr = 10, 0.1
updater = torch.optim.SGD(params, lr=lr)
d2l.train_ch3(
net, train_iter, test_iter, loss, num_epochs, updater)

train_iter, test_iter,loss,updater以及其内的params都是torch.nn调用的

其余是自定义的,net函数以及一些数字变量

softmax从零实现

一些工具

torch的矩阵乘法matmul

就是矩阵乘法AB

张量.numel返回张量元素数 

在PyTorch中,`.numel()` 是一个Tensor(张量)的方法,用于返回该张量的元素数量。这里的 "y" 应该是一个Tensor对象,它可能代表了一个标签或类别的向量。
具体来说,`.numel()` 方法会计算张量中所有元素的个数,不考虑张量的形状或维度。例如,对于一个形状为 `(3, 4)` 的二维张量,`.numel()` 会返回 \(3 \times 4 = 12\),表示这个张量总共有12个元素。
在你的代码片段中,`y.numel()` 可能被用来获取类别总数,这在某些情况下是需要的,比如计算某个统计量时需要知道总的样本数。
 

zip

list1 = [1, 2, 3]
list2 = ['a', 'b', 'c']
zipped = zip(list1, list2)
print(list(zipped))  # 输出: [(1, 'a'), (2, 'b'), (3, 'c')]

isinstance(a,b)判断a是否是b类

在Python中,isinstance() 是一个内置函数,用于检查一个对象是否是一个特定类型的实例,或者是其子类的实例。它的基本语法如下:

python

isinstance(object, classinfo)

其中:

  • object 是要检查的对象;
  • classinfo 可以是一个类,也可以是一个类型(tuple),比如 (int, str)

isinstance() 会根据 classinfo 参数来判断 object 是否为指定的数据类型。如果是,则返回 True;否则返回 False

 反向传播  张量.backward()

Q:反向传播函数需要自己写吗?还是每次只要.backward就行了?

A:在PyTorch中,通常不需要自己手动编写反向传播函数。PyTorch的自动微分(autograd)系统已经为大多数常见的数学运算提供了内置的反向传播函数。当你使用PyTorch的张量(tensor)进行操作时,这些操作会被记录在一个计算图中,PyTorch能够自动地计算并应用链式法则来执行反向传播。

因此,对于大多数情况,你只需要在计算完损失函数之后调用 .backward() 方法,PyTorch就会自动处理反向传播过程。

import torch

# 假设有一些输入数据和标签
x = torch.randn(5, requires_grad=True)
y = torch.randn(5)

# 定义一个线性模型
linear_model = torch.nn.Linear(5, 1)

# 计算模型的输出
predictions = linear_model(x)

# 定义损失函数
loss = torch.nn.functional.mse_loss(predictions, y)

# 反向传播
loss.backward()

# 现在可以访问模型的梯度
print(linear_model.weight.grad)
print(linear_model.bias.grad)

backward()看似只是一行代码,没有任何赋值,实际上是update的迭代更新需要访问梯度,backward求出了梯度的值存储在哪里以便直接访问了 。

.backward() 方法被调用来计算损失函数关于模型参数的梯度。这些梯度是自动累积在参数的 .grad 属性中的。然后,优化器(updater)使用这些梯度来更新模型的参数。

下面是详细的过程:

  1. l.mean().backward() 或 l.sum().backward():这行代码计算了损失函数 l 关于模型参数的梯度,并将这些梯度保存在每个参数的 .grad 属性中。

  2. updater.zero_grad():在调用 .backward() 之前,这行代码清除了过往的梯度。这是必须的,因为默认情况下,梯度是累积的(即每次调用 .backward() 时,梯度会加到之前的梯度上)。

  3. updater.step():这行代码使用计算出的梯度来更新模型的参数。这是优化器的一个方法,它执行了实际的参数更新步骤。

在 updater.step() 调用之后,模型的参数就被更新了,这是 .backward() 的结果被使用的地方。这个过程在训练循环的每次迭代中都会发生,因此模型的参数会在每个批次的数据处理后逐渐改进。

总结一下,.backward() 的结果是用来更新模型参数的,这个更新是通过优化器的 step() 方法实现的。在代码中没有直接显示使用 .backward() 的结果,因为这是通过优化器内部机制隐式完成的。

绘制动画

这里先不详细看,使用了animate类

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, 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)

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_metrics
    assert train_loss < 0.5, train_loss
    assert train_acc <= 1 and train_acc > 0.7, train_acc
    assert test_acc <= 1 and test_acc > 0.7, test_acc

损失函数的定义

def cross_entropy(y_hat, y):
    return - torch.log(y_hat[range(len(y_hat)), y])

cross_entropy(y_hat, y)

就是一个有着两个输入的函数

(预测值,真实值)

定义accuracy

def accuracy(y_hat, y):  #@save
    """计算预测正确的数量"""
    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())

就是一个有着两个输入的函数

(预测值,真实值)

定义精度(net模型,data_iter数据集)

同样,对于任意数据迭代器data_iter可访问的数据集, 我们可以评估在任意模型net的精度。

MXNETPYTORCHTENSORFLOWPADDLE

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]

data_iter是二元元祖(输入特征X,输出类别y)构成的可迭代列表,每个元祖是一个样本。

定义的Accumulator(2)

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

class Accumulator:  #@save
    """在n个变量上累加"""
    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]

解释:

metric.add(accuracy(net(X), y), y.numel())这里accuracy(net(X), y), y.numel()都是args

不妨设某次迭代前metric的值为(x1,x2)

迭代的传入的args为(acc,y.numel)

则经过metric.add(accuracy(net(X), y), y.numel())之后,metric变成了(x1+acc,x2+y.numel)

而metric初值为(0,0)

所以最后metric为(所有样本acc之和,所有样本的特征数之和(特征数*样本数))

定义net

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

输入是torch张量,输出也是

定义训练函数

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]

解释 

def train_epoch_ch3(net, train_iter, loss, updater):  #@save
    """训练模型一个迭代周期(定义见第3章)"""
  • 定义一个名为 train_epoch_ch3 的函数,它接受四个参数:net(神经网络模型)、train_iter(训练数据迭代器)、loss(损失函数)和 updater(优化器或自定义更新规则)。
  • 使用 #@save 注释标记该函数,这可能是一个特殊的标记,用于保存或记录函数定义。

    # 将模型设置为训练模式
    if isinstance(net, torch.nn.Module):
        net.train()
  • 检查 net 是否是 torch.nn.Module 类的一个实例(即是否是一个PyTorch模型)。
  • 如果是,调用 net.train() 方法将模型设置为训练模式。在训练模式下,某些层(如Dropout和BatchNorm)的行为会有所不同。

    # 训练损失总和、训练准确度总和、样本数
    metric = Accumulator(3)
  • 初始化一个名为 metric 的 Accumulator 实例,用于累积训练损失总和、训练准确度总和和样本数。Accumulator 可能是一个自定义的类,用于简化统计数据的累积。

    for X, y in train_iter:
  • 遍历 train_iter 迭代器,每次迭代获取一个批量数据 X 和对应的标签 y

        # 计算梯度并更新参数
        y_hat = net(X)
  • 使用模型 net 对输入数据 X 进行前向传播,得到预测结果 y_hat

        l = loss(y_hat, y)
  • 使用损失函数 loss 计算 y_hat 和真实标签 y 之间的损失 l

        if isinstance(updater, torch.optim.Optimizer):
  • 检查 updater 是否是 torch.optim.Optimizer 类的一个实例,即是否是一个PyTorch内置的优化器。

            # 使用PyTorch内置的优化器和损失函数
            updater.zero_grad()
  • 如果 updater 是内置优化器,调用 updater.zero_grad() 清除模型参数的梯度

            l.mean().backward()
  • 计算损失 l 的平均值,并调用 .backward() 方法进行反向传播,计算梯度

            updater.step()
  • 调用 updater.step() 更新模型的参数。

        else:
            # 使用定制的优化器和损失函数
            l.sum().backward()
  • 如果 updater 不是内置优化器,则计算损失 l 的总和,并调用 .backward() 方法进行反向传播。

            updater(X.shape[0])
  • 调用自定义的 updater 函数,可能传入批量大小的参数 X.shape[0](有多少个样本就是几),用于更新模型参数。

        metric.add(float(l.sum()), accuracy(y_hat, y), y.numel())
  • 使用 metric.add() 方法累积当前批量的损失总和、准确度和样本数。accuracy(y_hat, y) 可能是一个计算准确度的自定义函数,而 y.numel() 返回标签张量中的元素数量。

    # 返回训练损失和训练精度
    return metric[0] / metric[2], metric[1] / metric[2]
  • 计算并返回整个迭代周期的平均训练损失(总损失除以样本数)和平均训练精度(总准确度除以样本数)。

定义updater()

lr = 0.1

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

这里是使用了d2l现成的()

训练

num_epochs = 10
train_ch3(net, train_iter, test_iter, cross_entropy, num_epochs, updater)

使用训好的net预测 

def predict_ch3(net, test_iter, n=6):  #@save
    """预测标签(定义见第3章)"""
    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)

解释 

def predict_ch3(net, test_iter, n=6):  #@save
    """预测标签(定义见第3章)"""
  • 定义一个名为 predict_ch3 的函数,它接受三个参数:net(神经网络模型)、test_iter(测试数据迭代器)和 n(默认值为6,表示要显示的图像数量)。

    for X, y in test_iter:
        break
  • 遍历 test_iter 迭代器以获取测试数据集的第一个批次的数据 X(图像)和标签 y,然后立即退出循环。

这里是想展示一下第一个X,y的预测效果,所以就拿了第一批的样本(第一批,也有很多,就像后面的图上。)

    trues = d2l.get_fashion_mnist_labels(y)
  • 调用 d2l.get_fashion_mnist_labels 函数(假设这是一个自定义函数,用于将标签索引转换为可读的标签字符串),并将真实标签 y 作为输入,获取真实标签的字符串表示。

    preds = d2l.get_fashion_mnist_labels(net(X).argmax(axis=1))
  • 使用神经网络 net 对输入数据 X 进行预测,得到预测结果。.argmax(axis=1) 用于获取每个样本预测结果中的最大值索引(即预测的类别)。然后,使用 d2l.get_fashion_mnist_labels 函数将预测的类别索引转换为可读的标签字符串。

    titles = [true +'\n' + pred for true, pred in zip(trues, preds)]
  • 创建一个标题列表 titles,其中每个标题由真实标签和预测标签组成,中间用换行符分隔。

    d2l.show_images(
        X[0:n].reshape((n, 28, 28)), 1, n, titles=titles[0:n])
  • 调用 d2l.show_images 函数(假设这也是一个自定义函数,用于显示图像)来显示前 n 张图像。X[0:n].reshape((n, 28, 28)) 将前 n 张图像的数据重塑为适合显示的形状(每张图像是28x28像素)。1 表示图像的行数,n 表示列数,titles=titles[0:n] 将之前创建的标题与图像一起显示。

就是画图和显示

predict_ch3(net, test_iter)
  • 调用 predict_ch3 函数,传入模型 net 和测试数据迭代器 test_iter,执行预测并显示结果。

这个函数的作用是使用给定的神经网络模型对测试数据集的前 n 张图像进行预测,并将预测结果与真实标签一起显示出来。

画的图——

 (2024年10月27日终于知道为什么当时从CNN开始看看不懂了,基础的都在这里讲了。。。)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2225485.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

k8s部署使用有状态服务statefulset部署eureka集群,需登录认证

一、构建eureka集群镜像 1、编写dockerfile文件&#xff0c;此处基础镜像为arm版本&#xff0c;eureka目录中文件内容&#xff1a;application-dev.yml、Dockerfile、eureka-server-1.0-SNAPSHOT.jar(添加登录认证模块&#xff0c;文章最后附上下载连接) FROM mdsol/java8-j…

深入探索:深度学习在时间序列预测中的强大应用与实现

引言&#xff1a; 时间序列分析是数据科学和机器学习中一个重要的研究领域&#xff0c;广泛应用于金融市场、天气预报、能源管理、交通预测、健康监控等多个领域。时间序列数据具有顺序相关性&#xff0c;通常展示出时间上较强的依赖性&#xff0c;因此简单的传统回归模型往往…

基于SpringBoot的“社区维修平台”的设计与实现(源码+数据库+文档+PPT)

基于SpringBoot的“社区维修平台”的设计与实现&#xff08;源码数据库文档PPT) 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 管理员登录页面 住户管理页面 社区公关管理页面 维…

【JVM】——JVM运行机制、类加载机制、内存划分

阿华代码&#xff0c;不是逆风&#xff0c;就是我疯 你们的点赞收藏是我前进最大的动力&#xff01;&#xff01; 希望本文内容能够帮助到你&#xff01;&#xff01; 目录 一&#xff1a;JVM引入 1&#xff1a;编程语言 2&#xff1a;JAVA运行机制 二&#xff1a;JVM中内存…

EVADC模块多路触发导致AD值波动

前言&#xff1a;最近开发中遇到一个问题&#xff0c;某一路ADC通道采集的AD值波动比较厉害&#xff0c;达到9个hex值波动&#xff0c;对此进行了分析排查...... 1 排除硬件因素 用示波器对电路图上该ADC通道的测试点进行电压测量&#xff0c;发现电压比较稳定&#xff0c;换算…

【计算机网络三】一篇文章详解TCP/IP四层协议簇

目录 TCP/IP四层协议簇 1.应用层 DNS NAT NAPT HTTP/HTTPS 2.传输层 TCP协议 UDP协议 3.网络层 IP协议 4.数据链路层 以太网 ARP协议 TCP/IP四层协议簇 TCP/IP四层协议簇是目前世界上最流行的网络协议分层方式&#xff0c;本篇文章我将带大家从上到下详解四层协议…

开放式蓝牙耳机哪个品牌好用?爆款开放式耳机推荐!

在当今蓝牙耳机市场中&#xff0c;开放式蓝牙耳机以其独特的设计和舒适的佩戴体验&#xff0c;逐渐成为众多消费者的新宠。然而&#xff0c;面对众多品牌和款式的开放式蓝牙耳机&#xff0c;消费者往往陷入选择的困境。究竟哪个品牌的开放式蓝牙耳机真正好用&#xff1f;其性能…

Python实现贝叶斯优化器(Bayes_opt)优化简单循环神经网络回归模型(SimpleRNN回归算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后关注获取。 1.项目背景 贝叶斯优化器 (BayesianOptimization) 是一种黑盒子优化器&#xff0c;用来寻找最优参数。 贝叶斯…

C#使用开源库EasyModbusTCP跟PLC进行通讯开发步骤

使用C#进行非标自动化系统开发一般涉及的知识包含后台、前台、手持终端、客户端软件等功能模块的开发&#xff0c;其中后台程序连接数据库&#xff0c;而前台Vue界面&#xff0c;手持终端Android程序&#xff0c;客户端C#软件都会跟后台接口程序进行数据交换。 本文主要讨论C#客…

基于知识图谱的紧急事故决策辅助系统

现代社会紧急事故频发&#xff0c;而处理这些突发事件的效率直接决定了后续影响的大小。这时候&#xff0c;数据智能的解决方案会显得尤为重要&#xff01;今天为大家分享一个用【知识图谱】技术驱动的紧急事故决策辅助系统&#xff0c;不仅能帮助你快速处理事故信息&#xff0…

当有违法数据时,浏览器不解析,返回了undefined,导致数据不解析

现象&#xff1a;页面上没有看到数据 排查&#xff1a;断点到线上的源码里&#xff1a;1、协议回调确实没有拿到数据是个undefined 2、network里看服务确实响应了数据 3、控制台没有任何报错。 心情&#xff1a;莫名其妙的现象 我本地有json格式化工具&#xff0c;copy进去后&…

STM32硬件平台

STM32 系列是 STMicroelectronics 设计的高度灵活、广泛应用的微控制器&#xff08;MCU&#xff09;系列&#xff0c;支持从低功耗应用到高性能处理的需求&#xff0c;适用于工业、汽车、消费电子和物联网等广泛领域。STM32 系列具有广泛的硬件种类和丰富的功能&#xff0c;以下…

uniapp 引入了uview-ui后,打包错误,主包过大解决方案

原因&#xff1a;由于使用uniapp来设计小程序&#xff0c;使用uview的组件库&#xff0c;导致了主包过大&#xff0c;无法打包 前提条件&#xff1a;已经完成了分包&#xff0c;如果还没有分包的先分包&#xff0c;需要上传代码时用到 1. 通常情况&#xff0c;大多数都是通过点…

VUE3实现古典音乐网站源码模板

文章目录 1.设计来源1.1 网站首页页面1.2 古典音乐页面1.3 著名人物页面1.4 古典乐器页面1.5 历史起源页面1.6 登录页面1.7 注册页面 2.效果和源码2.1 动态效果2.2 目录结构 源码下载万套模板&#xff0c;程序开发&#xff0c;在线开发&#xff0c;在线沟通 作者&#xff1a;xc…

MIT 6.824 Lab1记录

MapReduce论文阅读 1. 编程模型 Map 函数&#xff08;kv -> kv&#xff09; Map 函数将输入的键值对处理为一系列中间值&#xff08;键值对&#xff09;&#xff0c;并将所有的中间结果传递给 Reduce 处理。 map(String key, String value):// key: document name// val…

PHP员工管理系统小程序

&#x1f4bc;高效管理&#xff0c;从“员工管理系统”开始&#x1f4bc; &#x1f4cb;【一键录入&#xff0c;信息整合】&#x1f4cb; 你是否还在为整理员工信息而手忙脚乱&#xff1f;纸质档案易丢失、电子表格易混乱&#xff0c;这些问题在“员工管理系统”面前都将迎刃…

如何使用ssm实现电商扶贫平台网站

TOC 10929ssm电商扶贫平台网站 第1章 绪论 1.1背景及意义 系统管理也都将通过计算机进行整体智能化操作&#xff0c;对于电商扶贫平台网站 所牵扯的管理及数据保存都是非常多的&#xff0c;例如管理员&#xff1b;首页、个人中心、商品分类管理、热门商品管理、用户管理、系…

Android 应用申请 Google MBA权限

​ Google Case链接&#xff1a;89 > 34810 > 30025 > 155353 > Handheld > MBA Policies 按照指引填写模板 This bug is for the approval of MBAs under [13.2.2 Pregrant permissions policy](https://docs.partner.android.com/gms/policies/domains/mba#m…

DS3231时钟芯片全解析——概况,性能,MCU连接,样例代码

DS3231概述&#xff1a; 数据&#xff1a; DS3231是一个超高精度I2C实时时钟芯片&#xff0c;带有集成的温度补偿晶振。误差范围&#xff1a;温度范围为0摄氏度到40摄氏度&#xff08;2PPM&#xff09;&#xff0c;温度范围为-40摄氏度到85摄氏度&#xff08;3.5PPM&#xff0c…

栈和队列-栈的练习题

1. 逆波兰表达式 题目: 给出一个算数式的后缀表达式,我们来求他最后算数值. 在解题之前我们来认识一下中缀表达式,和后缀表达式(逆波兰表达式 我们在写数学遇到的那种形式的算数表达式就是中缀表达式,我们要从中缀表达式变为后缀表达式(逆波兰式),计算机时不知道式子的计算…