深度学习 精选笔记(4)线性神经网络-交叉熵回归与Softmax 回归

news2025/2/25 5:06:39

学习参考:

  • 动手学深度学习2.0
  • Deep-Learning-with-TensorFlow-book
  • pytorchlightning

①如有冒犯、请联系侵删。
②已写完的笔记文章会不定时一直修订修改(删、改、增),以达到集多方教程的精华于一文的目的。
③非常推荐上面(学习参考)的前两个教程,在网上是开源免费的,写的很棒,不管是开始学还是复习巩固都很不错的。

深度学习回顾,专栏内容来源多个书籍笔记、在线笔记、以及自己的感想、想法,佛系更新。争取内容全面而不失重点。完结时间到了也会一直更新下去,已写完的笔记文章会不定时一直修订修改(删、改、增),以达到集多方教程的精华于一文的目的。所有文章涉及的教程都会写在开头、一起学习一起进步。

一、交叉熵回归

交叉熵回归(Cross-Entropy Regression):交叉熵是一种用于衡量两个概率分布之间差异的指标,在机器学习中常用于分类问题的损失函数。交叉熵回归通常用于二分类问题,其中模型输出的是一个概率值,表示样本属于某一类的概率,损失函数是交叉熵损失函数。交叉熵损失函数可以表示为:
在这里插入图片描述

二、Softmax 回归

Softmax 回归:Softmax 回归是一种多分类模型,用于将模型的输出转化为多个类别的概率分布。在 Softmax 回归中,模型的最后一层是一个 Softmax 函数,将模型的输出转化为每个类别的概率,使得所有类别的概率之和为 1。
在这里插入图片描述

交叉熵回归通常用于二分类问题,而 Softmax 回归用于多分类问题。此外,Softmax 回归中的 Softmax 函数将模型输出转化为概率分布,而交叉熵回归中的损失函数用于衡量二分类模型输出与真实标签的差异。

1.分类问题

分类任务是机器学习和统计学中常见的一类任务,其目标是将数据集中的样本划分到预定义的类别或标签中。分类任务通常涉及预测离散的输出值,即将样本分为不同的类别。例如,将电子邮件分为“垃圾邮件”和“非垃圾邮件”、将图片识别为“猫”、“狗”或“鸟”等。

分类问题是指解决这类分类任务的问题。分类问题的关键在于构建一个分类模型,该模型可以根据输入的特征将样本正确地分配到各个类别中。常用的分类算法包括逻辑回归、支持向量机(SVM)、决策树、随机森林、K近邻(K-NN)等。

一种表示分类数据的简单方法:独热编码(one-hot encoding)。 独热编码是一个向量,它的分量和类别一样多。 类别对应的分量设置为1,其他所有分量设置为0。 从一个图像分类问题开始,假设每个图像属于类别“猫”“鸡”和“狗”中的一个、每次输入是一个 2×2 的灰度图像、每个图像对应四个特征𝑥1,𝑥2,𝑥3,𝑥4。标签 𝑦将是一个三维向量, 其中 (1,0,0) 对应于“猫”、 (0,1,0) 对应于“鸡”、 (0,0,1) 对应于“狗”。
在这里插入图片描述

2.网络结构

为了估计所有可能类别的条件概率,需要一个有多个输出的模型,每个类别对应一个输出。 为了解决线性模型的分类问题,需要和输出一样多的仿射函数(affine function)。 每个输出对应于它自己的仿射函数。

在识别猫、鸡、狗的任务中,为每个输入计算三个未规范化的预测(logit):𝑜1、𝑜2和𝑜3:
在这里插入图片描述
与线性回归一样,softmax回归也是一个单层神经网络。 由于计算每个输出 𝑜1 、 𝑜2 和 𝑜3取决于 所有输入 𝑥1 、 𝑥2 、 𝑥3 和 𝑥4 , 所以softmax回归的输出层也是全连接层。
在这里插入图片描述
通过向量形式表达为𝐨=𝐖𝐱+𝐛, 这是一种更适合数学和编写代码的形式。 由此,已经将所有权重放到一个3×4矩阵中。 对于给定数据样本的特征𝐱, 输出是由权重与输入特征进行矩阵-向量乘法再加上偏置𝐛得到的。

3.softmax运算

将优化参数以最大化观测数据的概率。 为了得到预测结果,将设置一个阈值,如选择具有最大概率的标签。

softmax函数能够将未规范化的预测变换为非负数并且总和为1,同时让模型保持 可导的性质。 为了完成这一目标,我们首先对每个未规范化的预测求幂,这样可以确保输出非负。 为了确保最终输出的概率值总和为1,我们再让每个求幂后的结果除以它们的总和。如下式:
在这里插入图片描述
因此, 𝐲̂ 可以视为一个正确的概率分布。 softmax运算不会改变未规范化的预测 𝐨之间的大小次序,只会确定分配给每个类别的概率。 因此,在预测过程中,仍然可以用下式来选择最有可能的类别。

在这里插入图片描述
尽管softmax是一个非线性函数,但softmax回归的输出仍然由输入特征的仿射变换决定。 因此,softmax回归是一个线性模型(linear model)。

4.小批量样本的矢量化

为了提高计算效率并且充分利用GPU,通常会对小批量样本的数据执行矢量计算。 softmax回归的矢量计算表达式为:
在这里插入图片描述
相对于一次处理一个样本, 小批量样本的矢量化加快了 𝐗和𝐖的矩阵-向量乘法。 由于 𝐗中的每一行代表一个数据样本, 那么softmax运算可以按行(rowwise)执行: 对于 𝐎 的每一行,先对所有项进行幂运算,然后通过求和对它们进行标准化。

5.损失函数

需要一个损失函数来度量预测的效果。 将使用最大似然估计,这与在线性回归中相同。

(1)对数似然

softmax函数给出了一个向量 𝐲̂ , 可以将其视为“对给定任意输入 𝐱的每个类的条件概率”。 例如, 𝑦̂ 1 = 𝑃(𝑦=猫∣𝐱)。 假设整个数据集 {𝐗,𝐘}具有 𝑛个样本, 其中索引 𝑖的样本由特征向量 𝐱(𝑖)和独热标签向量 𝐲(𝑖)组成。 可以将估计值与实际值进行比较:
在这里插入图片描述
根据最大似然估计,最大化 𝑃(𝐘∣𝐗) ,相当于最小化负对数似然:
在这里插入图片描述
其中,对于任何标签 𝐲和模型预测 𝐲̂ ,损失函数为:
在这里插入图片描述
上述损失函数 通常被称为交叉熵损失公式(cross-entropy loss)

(2)softmax及其导数

由于softmax和相关的损失函数很常见, 因此需要更好地理解它的计算方式。将𝐲̂ =softmax(𝐨) 代入交叉熵损失公式中,得到:
在这里插入图片描述
考虑相对于任何未规范化的预测 𝑜𝑗 的导数,得到:
在这里插入图片描述
上述最终导数表示,导数是softmax模型分配的概率与实际发生的情况(由独热标签向量表示)之间的差异。

(3)交叉熵损失

定义损失 𝑙, 它是所有标签分布的预期损失值。 此损失称为交叉熵损失(cross-entropy loss),它是分类问题最常用的损失之一。
在这里插入图片描述

用一个概率向量表示来阐述整个结果的分布情况,如 (0.1,0.2,0.7), 而不是仅包含二元项的向量 (0,0,1) ,,即观察到的不仅仅是一个结果。

6.模型预测和评估

在训练softmax回归模型后,给出任何样本特征,便可以预测每个输出类别的概率。 通常使用预测概率最高的类别作为输出类别。 如果预测与实际类别(标签)一致,则预测是正确的。最后使用精度(accuracy)来评估模型的性能。 精度等于正确预测数与预测总数之间的比率。

三、Fashion-MNIST图片分类数据集

1.加载数据集

通过框架中的内置函数将Fashion-MNIST数据集下载并读取到内存中。Fashion-MNIST由10个类别的图像组成, 每个类别由训练数据集(train dataset)中的6000张图像 和测试数据集(test dataset)中的1000张图像组成。 因此,训练集和测试集分别包含60000和10000张图像。 测试数据集不会用于训练,只用于评估模型性能。

每个输入图像的高度和宽度均为28像素。 数据集由灰度图像组成,其通道数为1。 为了简洁起见、将高度 ℎ 像素、宽度 𝑤像素图像的形状记为 ℎ×𝑤或( ℎ , 𝑤 )。

%matplotlib inline
import tensorflow as tf
from d2l import tensorflow as d2l

d2l.use_svg_display()

#执行之后会启动下载数据集到本地,不建议开飞机再运行此代码下载、亲测会丢包导致数据不完整而报错。
mnist_train, mnist_test = tf.keras.datasets.fashion_mnist.load_data()

如果下载失败(通常是这个文件t10k-images-idx3-ubyte.gz失败),也可以直接访问 Fashion-MNIST 数据集的官方网站或者仓库:Fashion-MNIST.

  • 下载数据集文件夹。

  • 将这四个文件放置在您项目的数据集目录中,例如 ~/.keras/datasets/fashion-mnist/。

下载失败的话删除~/.keras/datasets/fashion-mnist/文件夹重新运行直到成功为止。

Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-labels-idx1-ubyte.gz
29515/29515 [==============================] - 0s 1us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-images-idx3-ubyte.gz
26421880/26421880 [==============================] - 6s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-labels-idx1-ubyte.gz
5148/5148 [==============================] - 0s 0s/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-images-idx3-ubyte.gz
4422102/4422102 [==============================] - 1s 0us/step

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)):
        ax.imshow(img.numpy())
        ax.axes.get_xaxis().set_visible(False)
        ax.axes.get_yaxis().set_visible(False)
        if titles:
            ax.set_title(titles[i])
    return axes

查看数据:

X = tf.constant(mnist_train[0][:10])
y = tf.constant(mnist_train[1][:10])
show_images(X, 2, 5, titles=get_fashion_mnist_labels(y));

在这里插入图片描述

2.读取小批量数据

为了在读取训练集和测试集时更容易,使用内置的数据迭代器,而不是从零开始创建。在每次迭代中,数据迭代器每次都会读取一小批量数据,大小为batch_size。 通过内置数据迭代器,可以随机打乱了所有样本,从而无偏见地读取小批量。

batch_size = 256
train_iter = tf.data.Dataset.from_tensor_slices(
    mnist_train).batch(batch_size).shuffle(len(mnist_train[0]))

数据迭代器是获得更高性能的关键组件。依靠实现良好的数据迭代器,利用高性能计算来避免减慢训练过程。

3.整合组件

def load_data_fashion_mnist(batch_size, resize=None):   #@save
    """下载Fashion-MNIST数据集,然后将其加载到内存中"""
    mnist_train, mnist_test = tf.keras.datasets.fashion_mnist.load_data()
    # 将所有数字除以255,使所有像素值介于0和1之间,在最后添加一个批处理维度,
    # 并将标签转换为int32。
    process = lambda X, y: (tf.expand_dims(X, axis=3) / 255,
                            tf.cast(y, dtype='int32'))
    resize_fn = lambda X, y: (
        tf.image.resize_with_pad(X, resize, resize) if resize else X, y)
    return (
        tf.data.Dataset.from_tensor_slices(process(*mnist_train)).batch(
            batch_size).shuffle(len(mnist_train[0])).map(resize_fn),
        tf.data.Dataset.from_tensor_slices(process(*mnist_test)).batch(
            batch_size).map(resize_fn))

通过指定resize参数来测试load_data_fashion_mnist函数的图像大小调整功能。

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

四、从0实现softmax回归

1.加载数据集

引入Fashion-MNIST数据集, 并设置数据迭代器的批量大小为256。

import tensorflow as tf
from IPython import display
from d2l import tensorflow as d2l


batch_size = 256
# load_data_fashion_mnist函数已封装在d2l模块里面可以直接调用。也可以调用上面的。
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)

2.初始化模型参数

输出与类别一样多。 (因为数据集有10个类别,所以网络输出维度为10)。 因此,权重将构成一个 784×10 的矩阵, 偏置将构成一个 1×10 的行向量。 与线性回归一样,将使用正态分布初始化权重W,偏置初始化为0。

num_inputs = 784
num_outputs = 10

W = tf.Variable(tf.random.normal(shape=(num_inputs, num_outputs),
                                 mean=0, stddev=0.01))
b = tf.Variable(tf.zeros(num_outputs))

3.定义softmax操作

实现softmax由三个步骤组成:

  • 对每个项求幂(使用exp);
  • 对每一行求和(小批量中每个样本是一行),得到每个样本的规范化常数;
  • 将每一行除以其规范化常数,确保结果的和为1。
def softmax(X):
    X_exp = tf.exp(X)
    partition = tf.reduce_sum(X_exp, 1, keepdims=True)
    return X_exp / partition  # 这里应用了广播机制

对于任何随机输入,将每个元素变成一个非负数。 此外,依据概率原理,每行总和为1。

4.定义模型

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

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

5.交叉熵损失函数

实现交叉熵损失函数

def cross_entropy(y_hat, y):
    return -tf.math.log(tf.boolean_mask(
        y_hat, tf.one_hot(y, depth=y_hat.shape[-1])))


6.分类精度

当预测与标签分类y一致时,即是正确的。 分类精度即正确预测数量与总预测数量之比。 虽然直接优化精度可能很困难(因为精度的计算不可导), 但精度通常是最关心的性能衡量标准,在训练分类器时几乎总会关注它。

def accuracy(y_hat, y):  #@save
    """计算预测正确的数量"""
    if len(y_hat.shape) > 1 and y_hat.shape[1] > 1:
        y_hat = tf.argmax(y_hat, axis=1)
    cmp = tf.cast(y_hat, y.dtype) == y
    return float(tf.reduce_sum(tf.cast(cmp, y.dtype)))

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

def evaluate_accuracy(net, data_iter):  #@save
    """计算在指定数据集上模型的精度"""
    metric = Accumulator(2)  # 正确预测数、预测总数
    for X, y in data_iter:
        metric.add(accuracy(net(X), y), d2l.size(y))
    return metric[0] / metric[1]

定义一个实用程序类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]

7.训练模型

定义一个函数来训练一个迭代周期。 请注意,updater是更新模型参数的常用函数,它接受批量大小作为参数。 它可以是d2l.sgd函数,也可以是框架的内置优化函数。

def train_epoch_ch3(net, train_iter, loss, updater):  #@save
    """训练模型一个迭代周期(定义见第3章)"""
    # 训练损失总和、训练准确度总和、样本数
    metric = Accumulator(3)
    for X, y in train_iter:
        # 计算梯度并更新参数
        with tf.GradientTape() as tape:
            y_hat = net(X)
            # Keras内置的损失接受的是(标签,预测),这不同于用户在本书中的实现。
            # 本书的实现接受(预测,标签),例如我们上面实现的“交叉熵”
            if isinstance(loss, tf.keras.losses.Loss):
                l = loss(y, y_hat)
            else:
                l = loss(y_hat, y)
        if isinstance(updater, tf.keras.optimizers.Optimizer):
            params = net.trainable_variables
            grads = tape.gradient(l, params)
            updater.apply_gradients(zip(grads, params))
        else:
            updater(X.shape[0], tape.gradient(l, updater.params))
        # Keras的loss默认返回一个批量的平均损失
        l_sum = l * float(tf.size(y)) if isinstance(
            loss, tf.keras.losses.Loss) else tf.reduce_sum(l)
        metric.add(l_sum, accuracy(y_hat, y), tf.size(y))
    # 返回训练损失和训练精度
    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, 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)

实现一个训练函数, 它会在train_iter访问到的训练数据集上训练一个模型net。 该训练函数将会运行多个迭代周期(由num_epochs指定)。 在每个迭代周期结束时,利用test_iter访问到的测试数据集对模型进行评估。

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

作为一个从零开始的实现,使用定义的 小批量随机梯度下降来优化模型的损失函数,设置学习率为0.1。

class Updater():  #@save
    """用小批量随机梯度下降法更新参数"""
    def __init__(self, params, lr):
        self.params = params
        self.lr = lr

    def __call__(self, batch_size, grads):
        d2l.sgd(self.params, grads, self.lr, batch_size)

updater = Updater([W, b], lr=0.1)

之前定义的小批量随机梯度下降如下,已经封装在d2l模块中了:

def sgd(params, grads, lr, batch_size):  #@save
    """小批量随机梯度下降"""
    for param, grad in zip(params, grads):
        param.assign_sub(lr*grad/batch_size)

训练模型50个迭代周期。 请注意,迭代周期(num_epochs)和学习率(lr)都是可调节的超参数。 通过更改它们的值,可以提高模型的分类精度。

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

在这里插入图片描述

8.预测

模型已经准备好对图像进行分类预测。 给定一系列图像,将比较它们的实际标签(文本输出的第一行)和模型预测(文本输出的第二行)。

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(tf.argmax(net(X), axis=1))
    titles = [true +'\n' + pred for true, pred in zip(trues, preds)]
    d2l.show_images(
        tf.reshape(X[0:n], (n, 28, 28)), 1, n, titles=titles[0:n])

predict_ch3(net, test_iter)

在这里插入图片描述

五、简洁实现softmax回归

softmax回归的输出层是一个全连接层,只需在Sequential中添加一个带有10个输出的全连接层。

import tensorflow as tf
from d2l import tensorflow as d2l

#加载数据集
batch_size = 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)

# 初始化模型参数,仍然以均值0和标准差0.01随机初始化权重。
net = tf.keras.models.Sequential()
net.add(tf.keras.layers.Flatten(input_shape=(28, 28)))
weight_initializer = tf.keras.initializers.RandomNormal(mean=0.0, stddev=0.01)
net.add(tf.keras.layers.Dense(10, kernel_initializer=weight_initializer))

# 交叉熵损失函数,在交叉熵损失函数中传递未规范化的预测,并同时计算softmax及其对数。
loss = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)

# 使用学习率为0.1的小批量随机梯度下降作为优化算法
trainer = tf.keras.optimizers.SGD(learning_rate=0.1)

# 调用之前定义的训练函数训练模型
num_epochs = 10
d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, trainer)

这里为什么是d2l.train_ch3函数来训练而不是类似tf内置的model.fit()呢?因为train_ch3函数里面已经封装好了训练过程和可视化功能。利用Animator类来可视化训练进度。
在这里插入图片描述
预测:

d2l.predict_ch3(net, test_iter)

在这里插入图片描述

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

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

相关文章

postman访问k8s api

第一种方式&#xff1a; kubectl -n kubesphere-system get sa kubesphere -oyaml apiVersion: v1 kind: ServiceAccount metadata:annotations:meta.helm.sh/release-name: ks-coremeta.helm.sh/release-namespace: kubesphere-systemcreationTimestamp: "2023-07-24T07…

影像仪激光扫描功能,无缝连接2D/3D混合测量

在现代工业生产领域&#xff0c;影像仪用于质量控制和产品检测&#xff0c;是一个不可或缺的工具。它通过高精度的成像和图像处理技术&#xff0c;可以及时发现产品的缺陷和异常&#xff0c;以保证产品质量的稳定性和一致性。 影像仪的重要性及其面临的挑战 在工业生产方面&a…

免杀实战-EDR对抗

文章目录 杀软分析BOF.NET 杀软分析 x64dgb简单调试发现该edr在r3环对ntdll.dll和kernel32.dll关键函数均存在hook&#xff0c;这里硬盘读取原来的dll进行重新加载&#xff0c;原理如图 loader // dllmain.cpp : 定义 DLL 应用程序的入口点。 #include "pch.h" #in…

矩阵的范数 matrix norm Frobenius norm 弗罗贝尼乌斯 范数

1&#xff0c;矩阵范数的定义 矩阵的范数&#xff0c;matrix norm即矩阵的模&#xff1b;它把一个矩阵空间变成为赋范线性空间&#xff1b; 从一个矩阵空间映射到非负实数的函数 满足以下条件&#xff1a; 1&#xff0c;严格的正定性。对于 , 则 ; and if , must ; 2&…

Element UI中 el-tree 组件 css 实现横向溢出滚动实现

限制 el-tree 的父容器宽度为 100px 之后 el-tree 组件内数据溢出后隐藏&#xff0c;不出现滚动条 、overflow 为 auto 也无效 overflow 无效是因为 el-tree 宽度 也是 100px 本来也就没有溢出 给 el-tree 添加样式 width: fit-content; min-width: -webkit-fill-available; …

【Nginx笔记02】通过Nginx服务器转发客户端的WebSocket接口到后端服务

这篇文章&#xff0c;主要介绍如何通过Nginx服务器转发客户端的WebSocket接口到后端服务【知识星球】。 目录 一、Nginx配置WebSocket 1.1、Nginx配置内容 1.2、客户端请求地址 1.3、创建WebSocket测试工程 1.4、启动测试 1.5、WebSocket超时问题 1.5.1、设置超时时间 …

一键生成任意前端项目

开始 方式一&#xff1a;根据数据库结构一键生成 方式二&#xff1a;根据&#xff08;.sql, .java, .txt&#xff09;描述文件单页面生成 总结 话不多说&#xff0c;作为后端开发人员&#xff0c;不爱写前端代码&#xff0c;但又不得不需要一个系统的管理端来配置些数据等等…

架构设计:生产消费模型

1. 引言 在现代软件系统中&#xff0c;处理大量数据和消息是一项重要的任务。生产消费模型作为一种经典的并发模式&#xff0c;在解决数据生产和消费之间的关系上发挥着关键作用。该模型通过有效地管理生产者和消费者之间的通信和数据流动&#xff0c;实现了系统组件之间的解耦…

【论文阅读】基于人工智能目标检测与跟踪技术的过冷流沸腾气泡特征提取

Bubble feature extraction in subcooled flow boiling using AI-based object detection and tracking techniques 基于人工智能目标检测与跟踪技术的过冷流沸腾气泡特征提取 期刊信息&#xff1a;International Journal of Heat and Mass Transfer 2024 级别&#xff1a;EI检…

【寸铁的刷题笔记】图论、bfs、dfs

【寸铁的刷题笔记】图论、bfs、dfs 大家好 我是寸铁&#x1f44a; 金三银四&#xff0c;图论基础结合bfs、dfs是必考的知识点✨ 快跟着寸铁刷起来&#xff01;面试顺利上岸&#x1f44b; 喜欢的小伙伴可以点点关注 &#x1f49d; &#x1f31e;详见如下专栏&#x1f31e; &…

2024年新提出的算法|鹦鹉优化器(Parrot optimizer):算法及其在医疗问题中的应用

本期介绍一种基于训练后鹦鹉关键行为的高效优化方法——鹦鹉优化器(Parrot Optimizer, PO)。该成果于2024年2月发表在中科院2区top SCI期刊Computers in Biology and Medicine&#xff08;IF7.7&#xff09; 1、简介 鹦鹉优化器&#xff08;PO&#xff09;是一种受训练有素的…

RocketMQ学习笔记(2)—— 集成SpringBoot

前置知识&#xff1a; RocketMQ学习笔记&#xff08;1&#xff09;—— 基础使用-CSDN博客 7.集成SpringBoot 以上所述功能均是通过RocketMQ的原生API实现的&#xff0c;除此之外SpringBoot对于一些功能进行了封装&#xff0c;使用更加方便 7.1 producer 依赖 <!-- rock…

新火种AI|微软扶持下一个OpenAI?Mistral AI新模型对标GPT-4,上线即挤爆

作者&#xff1a;一号 编辑&#xff1a;美美 OpenAI的大金主微软&#xff0c;还想缔造“下一个OpenAI”。 周一晚间&#xff0c;成立仅9个月的Mistral AI正式发布了最强力的旗舰模型Mistral Large。和此前他们所推出的一系列模型不同&#xff0c;Mistral AI本次发布的版本性…

TikTok矩阵系统的功能展示:深入解析与源代码分享!

今天我来和大家说说TikTok矩阵系统&#xff0c;在当今数字化时代&#xff0c;社交媒体平台已成为人们获取信息、交流思想和娱乐放松的重要渠道&#xff0c;其中&#xff0c;TikTok作为一款全球知名的短视频社交平台&#xff0c;凭借其独特的创意内容和强大的算法推荐系统&#…

有效防止CDN网站被溯源ip的教程

如何反溯源隐藏自己的源IP防止溯源&#xff1f; 还有些大牛会进行渗透攻击、CC攻击&#xff0c;溯源打服务器&#xff0c;各式各样的&#xff0c;防不胜防。所以很多站长套起了cdn&#xff0c;比起cdn提供的加速效果&#xff0c;更多的站长可能还是为了保护那可怜弱小的源站ip…

Docker(运维工具)—— 学习笔记

快速构建、运行、管理应用的工具 一、安装docker 参考Install Docker Engine on Ubuntu | Docker Docs 二、快速入门 1、镜像和容器 docker镜像可以做到忽略操作系统的差异&#xff0c;跨平台运行&#xff0c;忽略安装的差异 当我们利用Docker安装应用时&#xff0c;Dock…

关于机器学习梯度下降法以及牛顿法公式符号的解释

如下图&#xff0c;是公式 如上图红线画出的部分&#xff0c;就是梯度下降法的符号&#xff0c;或者说&#xff0c;是 J(theta) 损失函数的一阶导数 整个公式看起来&#xff0c;就是 theta_new theta_old - (一阶导数/二阶导数)

算法day01_ 27. 移除元素、977.有序数组的平方

推荐阅读 从零开始学数组&#xff1a;深入浅出&#xff0c;带你掌握核心要点 初探二分法 再探二分法 系统的纪录一下刷算法的过程&#xff0c;之前一直断断续续的刷题&#xff0c;半途而废&#xff0c;现在重新开始。话不多说&#xff0c;开冲&#xff01; 27.移除元素 题目 给…

Maven编译报processing instruction can not have PITarget with reserveld xml name

在java项目中&#xff0c;平时我们会执行mvn clean package命令来编译我们的java项目&#xff0c;可是博主今天执行编译时突然报了 processing instruction can not have PITarget with reserveld xml name 这个错&#xff0c;网上也说法不一&#xff0c;但是绝大绝大部分是因…

(二十)devops持续集成开发——使用jenkins的docker插件完成docker项目的流水线发布

前言 本节内容主要介绍jenkins如何集成docker插件&#xff0c;完成docker项目的流水线发布&#xff0c;在前面的章节中我们也介绍过docker项目的发布&#xff0c;可直接通过shell命令调用本地的docker服务完成docker项目的发布&#xff0c;本节内容我们使用docker插件来完成do…