探索 LeNet-5:卷积神经网络的先驱与手写数字识别传奇

一、引言

在当今深度学习技术蓬勃发展的时代,各种复杂而强大的神经网络架构不断涌现,如 ResNet、VGG、Transformer 等,它们在图像识别、自然语言处理、语音识别等众多领域都取得了令人瞩目的成果。然而,当我们回顾深度学习的发展历程时,不得不提到一个具有开创性意义的神经网络架构 ——LeNet-5。它是由 Yann LeCun 等人在 1998 年提出的,虽然在今天看来它的结构相对简单,但它却为后来深度学习的繁荣奠定了坚实的基础,尤其是在手写数字识别这一经典任务上,LeNet-5 展现出了卓越的性能,成为了计算机视觉领域的一座重要里程碑。

二、

一、引言

在当今深度学习技术蓬勃发展的时代,各种复杂而强大的神经网络架构不断涌现,如 ResNet、VGG、Transformer 等,它们在图像识别、自然语言处理、语音识别等众多领域都取得了令人瞩目的成果。然而,当我们回顾深度学习的发展历程时,不得不提到一个具有开创性意义的神经网络架构 ——LeNet-5。它是由 Yann LeCun 等人在 1998 年提出的,虽然在今天看来它的结构相对简单,但它却为后来深度学习的繁荣奠定了坚实的基础,尤其是在手写数字识别这一经典任务上,LeNet-5 展现出了卓越的性能,成为了计算机视觉领域的一座重要里程碑。

二、LeNet-5 网络架构剖析

(一)输入层

LeNet-5 的输入是手写数字的图像,通常为 32x32 的灰度图像。这一尺寸的选择是经过精心设计的,既能够保留足够的数字特征信息,又在当时的计算资源限制下能够进行有效的处理。

(二)卷积层 C1

这是网络的第一个卷积层,它使用了 6 个大小为 5x5 的卷积核,步长为 1。卷积操作后得到 6 个大小为 28x28 的特征图(因为 (32 - 5 + 1) = 28)。每个卷积核都在学习图像中的不同局部特征,例如边缘、线条等。在这一层,还会进行偏置的添加以及通过激活函数(通常为 Sigmoid 函数)进行非线性变换,以增强网络的表达能力。以下是使用 Python 和 TensorFlow 框架实现 C1 层的示例代码:

收起

python

import tensorflow as tf

# 定义输入图像占位符,形状为 [None, 32, 32, 1],None 表示批次大小可以动态变化
input_images = tf.placeholder(tf.float32, [None, 32, 32, 1])

# 定义 C1 层的卷积核
weights_c1 = tf.Variable(tf.truncated_normal([5, 5, 1, 6], stddev=0.1))
biases_c1 = tf.Variable(tf.constant(0.1, shape=[6]))

# 进行卷积操作
conv1 = tf.nn.conv2d(input_images, weights_c1, strides=[1, 1, 1, 1], padding='VALID')
# 添加偏置
conv1 = tf.nn.bias_add(conv1, biases_c1)
# 使用 Sigmoid 激活函数
c1_output = tf.nn.sigmoid(conv1)

(三)池化层 S2

S2 层是一个下采样层,采用了平均池化操作,池化核大小为 2x2,步长为 2。这一层的作用是对 C1 层输出的特征图进行降维,减少数据量,同时保留主要的特征信息。经过池化后,6 个特征图的大小变为 14x14。以下是 S2 层的代码实现:

收起

python

# 定义 S2 层的池化操作
pool2 = tf.nn.avg_pool(c1_output, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='VALID')

(四)卷积层 C3

C3 层使用了 16 个大小为 5x5 的卷积核,步长为 1。它的输入是 S2 层的输出,通过卷积操作得到 16 个大小为 10x10 的特征图。这一层的卷积核设计与 C1 层有所不同,它与 S2 层的某些特征图进行组合连接,这种连接方式有助于网络学习到更复杂的特征组合。示例代码如下:

收起

python

# 定义 C3 层的卷积核
weights_c3 = tf.Variable(tf.truncated_normal([5, 5, 6, 16], stddev=0.1))
biases_c3 = tf.Variable(tf.constant(0.1, shape=[16]))

# 进行卷积操作
conv3 = tf.nn.conv2d(pool2, weights_c3, strides=[1, 1, 1, 1], padding='VALID')
# 添加偏置
conv3 = tf.nn.bias_add(conv3, biases_c3)
# 使用 Sigmoid 激活函数
c3_output = tf.nn.sigmoid(conv3)

(五)池化层 S4

S4 层同样是平均池化层,池化核大小为 2x2,步长为 2,对 C3 层的输出进行下采样,得到 16 个大小为 5x5 的特征图。代码实现如下:

收起

python

# 定义 S4 层的池化操作
pool4 = tf.nn.avg_pool(c3_output, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='VALID')

(六)卷积层 C5

C5 层使用了 120 个大小为 5x5 的卷积核,步长为 1,对 S4 层的输出进行卷积操作,得到 120 个大小为 1x1 的特征图,此时数据已经被高度抽象化。代码如下:

收起

python

# 定义 C5 层的卷积核
weights_c5 = tf.Variable(tf.truncated_normal([5, 5, 16, 120], stddev=0.1))
biases_c5 = tf.Variable(tf.constant(0.1, shape=[120]))

# 进行卷积操作
conv5 = tf.nn.conv2d(pool4, weights_c5, strides=[1, 1, 1, 1], padding='VALID')
# 添加偏置
conv5 = tf.nn.bias_add(conv5, biases_c5)
# 使用 Sigmoid 激活函数
c5_output = tf.nn.sigmoid(conv5)

(七)全连接层 F6

F6 层是一个全连接层,它将 C5 层的 120 个神经元与 84 个神经元进行全连接,通过权重矩阵和偏置向量进行线性变换,并使用 Sigmoid 激活函数进行非线性变换。这一层进一步对特征进行整合和映射,提取更高级的特征表示。示例代码:

收起

python

# 将 C5 层的输出展平为一维向量
flattened = tf.reshape(c5_output, [-1, 120])

# 定义 F6 层的权重和偏置
weights_f6 = tf.Variable(tf.truncated_normal([120, 84], stddev=0.1))
biases_f6 = tf.Variable(tf.constant(0.1, shape=[84]))

# 进行全连接操作
f6_output = tf.nn.sigmoid(tf.matmul(flattened, weights_f6) + biases_f6)

(八)输出层

输出层由 10 个神经元组成,对应于 0 - 9 这 10 个数字类别。采用 softmax 激活函数将神经元的输出转换为每个类别的概率分布,从而确定输入图像最可能属于的数字类别。代码如下:

收起

python

# 定义输出层的权重和偏置
weights_out = tf.Variable(tf.truncated_normal([84, 10], stddev=0.1))
biases_out = tf.Variable(tf.constant(0.1, shape=[10]))

# 进行全连接操作并使用 softmax 激活函数
logits = tf.matmul(f6_output, weights_out) + biases_out
output = tf.nn.softmax(logits)

三、LeNet-5 在手写数字识别中的训练与应用

(一)数据集准备

常用的手写数字识别数据集是 MNIST 数据集,它包含了大量的手写数字图像及其对应的标签。在使用前,需要对数据集进行加载、预处理,例如将图像数据归一化到 0 - 1 之间,将标签进行 one-hot 编码等操作。以下是使用 TensorFlow 加载和预处理 MNIST 数据集的示例代码:

收起

python

from tensorflow.examples.tutorials.mnist import input_data

# 加载 MNIST 数据集
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)

# 获取训练集和测试集数据
train_images = mnist.train.images.reshape(-1, 32, 32, 1)
train_labels = mnist.train.labels
test_images = mnist.test.images.reshape(-1, 32, 32, 1)
test_labels = mnist.test.labels

(二)损失函数与优化器选择

在训练 LeNet-5 网络时,通常采用交叉熵损失函数来衡量模型预测结果与真实标签之间的差异。对于优化器,可以选择随机梯度下降(SGD)、Adagrad、Adadelta、Adam 等。这里以 Adam 优化器为例,示例代码如下:

收起

python

# 定义损失函数为交叉熵
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=train_labels))

# 选择 Adam 优化器并设置学习率
optimizer = tf.train.AdamOptimizer(learning_rate=0.001).minimize(loss)

(三)模型训练与评估

通过循环迭代训练数据集,不断更新网络的权重和偏置,使损失函数逐渐减小。在训练过程中,可以定期在测试集上评估模型的准确率,以监控模型的训练效果。以下是训练和评估模型的示例代码:

收起

python

# 初始化 TensorFlow 会话
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())

    # 训练循环
    for epoch in range(10):  # 假设训练 10 个轮次
        total_loss = 0
        for i in range(len(train_images) // batch_size):  # 按批次训练
            batch_images = train_images[i * batch_size:(i + 1) * batch_size]
            batch_labels = train_labels[i * batch_size:(i + 1) * batch_size]

            # 运行优化器并计算损失
            _, batch_loss = sess.run([optimizer, loss], feed_dict={input_images: batch_images, train_labels: batch_labels})
            total_loss += batch_loss

        # 计算平均损失
        average_loss = total_loss / (len(train_images) // batch_size)
        print(f"Epoch {epoch + 1}, Average Loss: {average_loss}")

        # 在测试集上评估模型准确率
        correct_prediction = tf.equal(tf.argmax(output, 1), tf.argmax(test_labels, 1))
        accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
        test_accuracy = sess.run(accuracy, feed_dict={input_images: test_images, train_labels: test_labels})
        print(f"Test Accuracy: {test_accuracy}")

四、LeNet-5 的影响与现代拓展

(一)对深度学习发展的深远影响

LeNet-5 的出现为深度学习的发展提供了重要的思路和实践经验。它证明了卷积神经网络在图像识别任务中的有效性,为后续众多神经网络架构的设计提供了参考范例。其引入的卷积层、池化层等基本结构组件成为了现代深度学习架构的标配,推动了深度学习在计算机视觉、语音识别、自然语言处理等多个领域的广泛应用和深入研究。

(二)现代拓展与改进

随着计算能力的大幅提升和数据量的爆炸式增长,现代神经网络在 LeNet-5 的基础上进行了大量的拓展和改进。例如,网络深度不断增加,出现了更深层次的架构如 AlexNet、VGGNet、ResNet 等,这些架构能够学习到更复杂、更抽象的特征表示,从而在各种图像识别任务中取得了更高的准确率。同时,在激活函数方面,也逐渐从 Sigmoid 函数转向了 ReLU 函数及其变种,有效缓解了梯度消失问题,提高了网络的训练效率。此外,在优化算法、正则化技术、数据增强等方面也都有了长足的发展,使得神经网络的性能得到了进一步提升。

五、结论

LeNet-5 作为卷积神经网络的先驱,在手写数字识别领域以及整个深度学习发展历程中都占据着不可替代的重要地位。它的网络架构设计简洁而有效,为我们理解卷积神经网络的工作原理提供了一个清晰的范例。虽然在现代深度学习的浪潮中,LeNet-5 的性能已经无法与更为先进的架构相媲美,但它所蕴含的创新思想和技术贡献却永远铭刻在深度学习的发展史上。通过对 LeNet-5 的深入研究,我们能够更好地把握深度学习的发展脉络,为未来神经网络架构的创新和应用开发提供有益的启示和借鉴。无论是对于深度学习的初学者还是专业研究人员,LeNet-5 都是一个值得深入学习和探究的经典之作。

(一)输入层

LeNet-5 的输入是手写数字的图像,通常为 32x32 的灰度图像。这一尺寸的选择是经过精心设计的,既能够保留足够的数字特征信息,又在当时的计算资源限制下能够进行有效的处理。

(二)卷积层 C1

这是网络的第一个卷积层,它使用了 6 个大小为 5x5 的卷积核,步长为 1。卷积操作后得到 6 个大小为 28x28 的特征图(因为 (32 - 5 + 1) = 28)。每个卷积核都在学习图像中的不同局部特征,例如边缘、线条等。在这一层,还会进行偏置的添加以及通过激活函数(通常为 Sigmoid 函数)进行非线性变换,以增强网络的表达能力。以下是使用 Python 和 TensorFlow 框架实现 C1 层的示例代码:

import tensorflow as tf

# 定义输入图像占位符,形状为 [None, 32, 32, 1],None 表示批次大小可以动态变化
input_images = tf.placeholder(tf.float32, [None, 32, 32, 1])

# 定义 C1 层的卷积核
weights_c1 = tf.Variable(tf.truncated_normal([5, 5, 1, 6], stddev=0.1))
biases_c1 = tf.Variable(tf.constant(0.1, shape=[6]))

# 进行卷积操作
conv1 = tf.nn.conv2d(input_images, weights_c1, strides=[1, 1, 1, 1], padding='VALID')
# 添加偏置
conv1 = tf.nn.bias_add(conv1, biases_c1)
# 使用 Sigmoid 激活函数
c1_output = tf.nn.sigmoid(conv1)

(三)池化层 S2

S2 层是一个下采样层,采用了平均池化操作,池化核大小为 2x2,步长为 2。这一层的作用是对 C1 层输出的特征图进行降维,减少数据量,同时保留主要的特征信息。经过池化后,6 个特征图的大小变为 14x14。以下是 S2 层的代码实现:

# 定义 S2 层的池化操作
pool2 = tf.nn.avg_pool(c1_output, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='VALID')

(四)卷积层 C3

C3 层使用了 16 个大小为 5x5 的卷积核,步长为 1。它的输入是 S2 层的输出,通过卷积操作得到 16 个大小为 10x10 的特征图。这一层的卷积核设计与 C1 层有所不同,它与 S2 层的某些特征图进行组合连接,这种连接方式有助于网络学习到更复杂的特征组合。示例代码如下:

# 定义 C3 层的卷积核
weights_c3 = tf.Variable(tf.truncated_normal([5, 5, 6, 16], stddev=0.1))
biases_c3 = tf.Variable(tf.constant(0.1, shape=[16]))

# 进行卷积操作
conv3 = tf.nn.conv2d(pool2, weights_c3, strides=[1, 1, 1, 1], padding='VALID')
# 添加偏置
conv3 = tf.nn.bias_add(conv3, biases_c3)
# 使用 Sigmoid 激活函数
c3_output = tf.nn.sigmoid(conv3)

(五)池化层 S4

S4 层同样是平均池化层,池化核大小为 2x2,步长为 2,对 C3 层的输出进行下采样,得到 16 个大小为 5x5 的特征图。代码实现如下:

# 定义 S4 层的池化操作
pool4 = tf.nn.avg_pool(c3_output, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='VALID')

(六)卷积层 C5

C5 层使用了 120 个大小为 5x5 的卷积核,步长为 1,对 S4 层的输出进行卷积操作,得到 120 个大小为 1x1 的特征图,此时数据已经被高度抽象化。代码如下:

# 定义 C5 层的卷积核
weights_c5 = tf.Variable(tf.truncated_normal([5, 5, 16, 120], stddev=0.1))
biases_c5 = tf.Variable(tf.constant(0.1, shape=[120]))

# 进行卷积操作
conv5 = tf.nn.conv2d(pool4, weights_c5, strides=[1, 1, 1, 1], padding='VALID')
# 添加偏置
conv5 = tf.nn.bias_add(conv5, biases_c5)
# 使用 Sigmoid 激活函数
c5_output = tf.nn.sigmoid(conv5)

(七)全连接层 F6

F6 层是一个全连接层,它将 C5 层的 120 个神经元与 84 个神经元进行全连接,通过权重矩阵和偏置向量进行线性变换,并使用 Sigmoid 激活函数进行非线性变换。这一层进一步对特征进行整合和映射,提取更高级的特征表示。示例代码:

# 将 C5 层的输出展平为一维向量
flattened = tf.reshape(c5_output, [-1, 120])

# 定义 F6 层的权重和偏置
weights_f6 = tf.Variable(tf.truncated_normal([120, 84], stddev=0.1))
biases_f6 = tf.Variable(tf.constant(0.1, shape=[84]))

# 进行全连接操作
f6_output = tf.nn.sigmoid(tf.matmul(flattened, weights_f6) + biases_f6)

(八)输出层

输出层由 10 个神经元组成,对应于 0 - 9 这 10 个数字类别。采用 softmax 激活函数将神经元的输出转换为每个类别的概率分布,从而确定输入图像最可能属于的数字类别。代码如下:

# 定义输出层的权重和偏置
weights_out = tf.Variable(tf.truncated_normal([84, 10], stddev=0.1))
biases_out = tf.Variable(tf.constant(0.1, shape=[10]))

# 进行全连接操作并使用 softmax 激活函数
logits = tf.matmul(f6_output, weights_out) + biases_out
output = tf.nn.softmax(logits)

三、LeNet-5 在手写数字识别中的训练与应用

(一)数据集准备

常用的手写数字识别数据集是 MNIST 数据集,它包含了大量的手写数字图像及其对应的标签。在使用前,需要对数据集进行加载、预处理,例如将图像数据归一化到 0 - 1 之间,将标签进行 one-hot 编码等操作。以下是使用 TensorFlow 加载和预处理 MNIST 数据集的示例代码:

from tensorflow.examples.tutorials.mnist import input_data

# 加载 MNIST 数据集
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)

# 获取训练集和测试集数据
train_images = mnist.train.images.reshape(-1, 32, 32, 1)
train_labels = mnist.train.labels
test_images = mnist.test.images.reshape(-1, 32, 32, 1)
test_labels = mnist.test.labels

(二)损失函数与优化器选择

在训练 LeNet-5 网络时,通常采用交叉熵损失函数来衡量模型预测结果与真实标签之间的差异。对于优化器,可以选择随机梯度下降(SGD)、Adagrad、Adadelta、Adam 等。这里以 Adam 优化器为例,示例代码如下:

# 定义损失函数为交叉熵
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=train_labels))

# 选择 Adam 优化器并设置学习率
optimizer = tf.train.AdamOptimizer(learning_rate=0.001).minimize(loss)

(三)模型训练与评估

通过循环迭代训练数据集,不断更新网络的权重和偏置,使损失函数逐渐减小。在训练过程中,可以定期在测试集上评估模型的准确率,以监控模型的训练效果。以下是训练和评估模型的示例代码:

# 初始化 TensorFlow 会话
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())

    # 训练循环
    for epoch in range(10):  # 假设训练 10 个轮次
        total_loss = 0
        for i in range(len(train_images) // batch_size):  # 按批次训练
            batch_images = train_images[i * batch_size:(i + 1) * batch_size]
            batch_labels = train_labels[i * batch_size:(i + 1) * batch_size]

            # 运行优化器并计算损失
            _, batch_loss = sess.run([optimizer, loss], feed_dict={input_images: batch_images, train_labels: batch_labels})
            total_loss += batch_loss

        # 计算平均损失
        average_loss = total_loss / (len(train_images) // batch_size)
        print(f"Epoch {epoch + 1}, Average Loss: {average_loss}")

        # 在测试集上评估模型准确率
        correct_prediction = tf.equal(tf.argmax(output, 1), tf.argmax(test_labels, 1))
        accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
        test_accuracy = sess.run(accuracy, feed_dict={input_images: test_images, train_labels: test_labels})
        print(f"Test Accuracy: {test_accuracy}")

四、LeNet-5 的影响与现代拓展

(一)对深度学习发展的深远影响

LeNet-5 的出现为深度学习的发展提供了重要的思路和实践经验。它证明了卷积神经网络在图像识别任务中的有效性,为后续众多神经网络架构的设计提供了参考范例。其引入的卷积层、池化层等基本结构组件成为了现代深度学习架构的标配,推动了深度学习在计算机视觉、语音识别、自然语言处理等多个领域的广泛应用和深入研究。

(二)现代拓展与改进

随着计算能力的大幅提升和数据量的爆炸式增长,现代神经网络在 LeNet-5 的基础上进行了大量的拓展和改进。例如,网络深度不断增加,出现了更深层次的架构如 AlexNet、VGGNet、ResNet 等,这些架构能够学习到更复杂、更抽象的特征表示,从而在各种图像识别任务中取得了更高的准确率。同时,在激活函数方面,也逐渐从 Sigmoid 函数转向了 ReLU 函数及其变种,有效缓解了梯度消失问题,提高了网络的训练效率。此外,在优化算法、正则化技术、数据增强等方面也都有了长足的发展,使得神经网络的性能得到了进一步提升。

五、结论

LeNet-5 作为卷积神经网络的先驱,在手写数字识别领域以及整个深度学习发展历程中都占据着不可替代的重要地位。它的网络架构设计简洁而有效,为我们理解卷积神经网络的工作原理提供了一个清晰的范例。虽然在现代深度学习的浪潮中,LeNet-5 的性能已经无法与更为先进的架构相媲美,但它所蕴含的创新思想和技术贡献却永远铭刻在深度学习的发展史上。通过对 LeNet-5 的深入研究,我们能够更好地把握深度学习的发展脉络,为未来神经网络架构的创新和应用开发提供有益的启示和借鉴。无论是对于深度学习的初学者还是专业研究人员,LeNet-5 都是一个值得深入学习和探究的经典之作。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

希迪智驾持续亏损8.2亿:毛利率下滑,冲刺“自动驾驶矿卡第一股”

《港湾商业观察》黄懿 近日,希迪智驾(湖南)股份有限公司(下称“希迪智驾”)向港交所主板递交上市申请,联席保荐人为中金公司、中信建投国际、中国平安资本(香港)。 资料显示&#…

Vue 提供了Transition,可以帮助你制作基于状态变化的过渡和动画

官方文档&#xff1a;https://cn.vuejs.org/guide/built-ins/transition.html Transition​ Vue 提供了两个内置组件&#xff0c;可以帮助你制作基于状态变化的过渡和动画&#xff1a; <Transition> 会在一个元素或组件进入和离开 DOM 时应用动画。本章节会介绍如何使用…

Ansible自动化运维(三)playbook剧本详解

Ansible自动化运维这部分我将会分为五个部分来为大家讲解 &#xff08;一&#xff09;介绍、无密钥登录、安装部署、设置主机清单 &#xff08;二&#xff09;Ansible 中的 ad-hoc 模式 模块详解&#xff08;15&#xff09;个 &#xff08;三&#xff09;Playbook 模式详解 …

【汽车】-- 燃油发动机3缸和4缸

3缸和4缸燃油发动机是小轿车常见的发动机配置。以下从结构特点、性能、经济性等方面对两者进行对比&#xff0c;并分析优缺点及使用注意事项&#xff1a; 1. 结构与运行原理 3缸发动机 特点&#xff1a;少一个气缸&#xff0c;内部零部件更少&#xff0c;整体结构更紧凑。优点…

如何在x86模拟器和鸿蒙API9如何使用MQTT模块ohos_mqtt

目录 引言 安装失败的原因 如何编译so文件的x86_64版本 下载源代码 安装NDK 代码编译 安装MQTT软件包 避免MQTT软件包自动升级 设置libs 客户端程序的编写 运行测试 结语 参考文献 引言 在上周的博客&#xff08;如何在鸿蒙API9和x86模拟器中使用MQTT-CSDN博客&am…

若依集成更好用的easyexcel

背景 若依使用的是apach poi并在此基础上进行封装apach poi的原生的api是很复杂的&#xff0c;若依简化了了此操作apach poi的上传速率和下载速率都是没有优化的&#xff0c;依赖于文件大小的限制在此前提下&#xff0c;如果没法满足客户的需求&#xff08;超大型文件的上传&am…

我们来学mysql -- 探讨win安装方式(安装篇)

题记 书接上回&#xff0c;在我们来学mysql – 闲聊(安装篇)中&#xff0c;拿到安装包&#xff0c;当宝贝一样揣在怀里 然而&#xff0c;还没捂热乎&#xff0c;得粉丝秘报&#xff0c;U哥&#xff0c;上篇文章用了滞后的官方文档&#xff0c;哈哈哈…内心的小倔强&#xff0c…

[WiFi] WiFi安全加密WEP Vs WPA Vs WPA2 Vs WPA3整理

WiFi安全标准时间线 WEP&#xff08;Wired Equivalent Privacy&#xff09; WEP最早于1997年推出&#xff0c;是为了保护无线网络上的数据通信而设计的。当时&#xff0c;Wi-Fi技术还处于起步阶段&#xff0c;人们开始意识到需要一种安全协议来防止未经授权的访问和窃听。WEP被…

05 在 Linux 使用 AXI DMA

DMA简介 DMA 是一种采用硬件实现存储器与存储器之间或存储器与外设之间直接进行高速数据传输的技术&#xff0c;传输过程无需 CPU 参与&#xff08;但是CPU需要提前配置传输规则&#xff09;&#xff0c;可以大大减轻 CPU 的负担。 DMA 存储传输的过程如下&#xff1a; CPU 向…

深入解析下oracle的number底层存储格式

oracle数据库中&#xff0c;number数据类型用来存储数值数据&#xff0c;它既可以存储负数数值&#xff0c;也可以存储正数数值。相对于其他类型数据&#xff0c;number格式的数据底层存储格式要复杂得多。今天我们就详细探究下oracle的number底层存储格式。 一、环境搭建 1.…

多速率信号处理

介绍 简单来说&#xff0c; 多速率信号处理&#xff0c;是指对同时存在两个以上数据速率的系统进行信号处理。多速率信号处理原理就是通过改变信号速率&#xff0c;以适应系统内部各个节点对信号速率的要求。这里的速率其实就是指采样率。 多速率技术已广泛应用于数字音频处理…

golang实现简单的redis服务

golang 手搓redis服务器仓库地址:实现思路: golang 手搓redis服务器 仓库地址: 仓库: https://github.com/dengjiayue/my-redis.git 实现思路: ● 协议: tcp通信 ● 数据包: 长度(4byte)方法(1byte)数据json ● 数据处理: 单线程map读写 ○ 依次处理待处理队列的请求(chan)…

ssd202d-badblock-坏块检测

这边文章讲述的是坏快检测功能 思路: 1.第一次烧录固件会实现跳坏块,但是后续使用会导致坏块的产生; 于是我在uboot环境变量添加了两个变量来控制坏快 lb_badnum = //坏块个数 lb_badoff = //坏块所在位置 2.第一次开机会根据lb_badnum是否存在判断,如果不存在则保存上…

Y3编辑器文档2:场景编辑

文章目录 一、操作区二、地图设置2.1 地图大小2.2 其它选项三、地形编辑3.1 地势3.2 地形3.3 通行(碰撞、通行和视野规则)3.4 植被四、物件放置4.1 单位4.1.1 单位的摆放与调整4.1.2 状态栏属性编辑4.2 装饰物摆放4.3 物品4.4 镜头4.4.1 镜头的基本参数4.4.2 镜头时间轴动画4…

windows将文件推给Android真机/实机

记录一下 因为以前只试过从真机实机中将文件推给windows 但是从windows只简单复制粘贴的话会一直报错。 1.电脑安装adb 2.手机开启开发者模式 usb调试 3.usb连接选择文件传输 4.推送命令adb push 文件路径 /sdcard/download 步骤1和2和3不作赘述&#xff0c;可以搜相关配置教程…

[机器学习] 监督学习之线性回归与逻辑回归

这里写目录标题 一、监督学习概述二、线性回归&#xff08;一&#xff09;模型表示&#xff08;二&#xff09;损失函数&#xff08;三&#xff09;梯度下降算法导入所需库生成模拟数据&#xff08;可替换为真实数据&#xff09;初始化参数并进行训练可视化损失函数随迭代次数的…

精准预测美国失业率和贫困率,谷歌人口动态基础模型PDFM已开源,可增强现有地理空间模型

疾病、经济危机、失业、灾害……人类世界长期以来被各种各样的问题「侵扰」&#xff0c;了解人口动态对于解决这类复杂的社会问题至关重要。 政府相关人员可以通过人口动态数据来模拟疾病的传播&#xff0c;预测房价和失业率&#xff0c;甚至预测经济危机。然而&#xff0c;在过…

E172 ASP.NET+SQL+C#+LW+图书管理系统的设计与实现 配置 源码 文档 全套资料

图书管理系统 1.项目摘要2. 系统的概述3.项目功能4.界面展示5.源码获取 1.项目摘要 摘 要 书籍是供人们获取并增长知识的主要途径&#xff0c;由于图书的种类较多&#xff0c;阅读者也较多&#xff0c;借阅量较大&#xff0c;且易出错&#xff0c;传统的图书借阅若还停留在手工…

aippt:AI 智能生成 PPT 的开源项目

aippt&#xff1a;AI 智能生成 PPT 的开源项目 在现代办公和学习中&#xff0c;PPT&#xff08;PowerPoint Presentation&#xff09;是一种非常重要的展示工具。然而&#xff0c;制作一份高质量的PPT往往需要花费大量的时间和精力。为了解决这一问题&#xff0c;aippt项目应运…

轮转数组

轮转数组 1、题目描述2、解答思路2.1、辅助数组2.2、原地反转 1、题目描述 给定一个整数数组 nums&#xff0c;将数组中的元素向右轮转 k 个位置&#xff0c;其中 k 是非负数。 2、解答思路 2.1、辅助数组 如果我们在原数组上通过覆盖元素会导致部分元素的丢失&#xff0c…