基于CNN神经网络的手写字符识别实验报告

作业要求

具体实验内容根据实际情况自拟,可以是传统的BP神经网络,Hopfield神经网络,也可以是深度学习相关内容。

数据集自选,可以是自建数据集,或MNIST,CIFAR10等公开数据集。

实验报告内容包括但不限于:

  1. 实验目标和动机,应明确说明输入数据,和网络输出数据;
  2. 所设计相关网络的基本架构;
  3. 核心架构的具体实现;
  4. 网络训练和推理过程及说明;
  5. 实验结果比对和分析;
  6. 总结和讨论
  7. … 可根据需要自行扩展

评分标准:符合上述内容和格式要求,80分

          根据算法原理介绍,算法实现,实验结果分析和讨论情况,加分0-5分;

          根据实验结果分析和讨论各种神经网络方法的优缺点,加分0~5分;

  讨论不同神经网络参数对性能的影响,并尝试比对,加分0~5分;

  有自己观点或体现自身工作量,加分0-10分;

          总分不超过100分。

目录

1. 实验目标和动机

2 CNN算法的基本原理

3 LeNet5网络基本架构

4 核心架构的具体实现

5 网络训练和推理过程及说明

6 实验结果对比和分析

6.1 不同神经网络参数对性能的影响

6.1.1 批处理大小

6.1.2 学习率

6.1.3 优化算法

6.1.4 激活函数

6.2 实验结果的分析

7. 各种神经网络方法的优缺点

7.1多层感知机(MLP)

7.2卷积神经网络(CNN)

7.3 循环神经网络(RNN)

7.4 长短期记忆网络(LSTM)和门控循环单元(GRU)

8.总结和讨论

9.附录

1. 实验目标和动机

实验的目标是使用MNIST数据集进行手写字符识别。MNIST数据集包含许多手写数字的图像,每个图像都是28x28像素的灰度图像,表示数字0到9。

实验动机是探索使用卷积神经网络(CNN)进行图像识别任务,并比较不同网络结构和参数配置对性能的影响。

输入数据: 28x28像素的灰度图像

网络输出数据: 预测的数字类别

2 CNN算法的基本原理

CNN是一种专门用于处理图像数据的深度学习模型,其核心原理包括卷积层、池化层和全连接层。

卷积神经网络利用卷积层来提取图像特征。卷积操作通过滑动卷积核在输入图像上提取局部特征,这有助于捕获图像中的边缘、纹理等信息,并保留空间关系。

池化层用于降维和减少特征图的大小,同时保留主要特征。最常见的池化操作是最大池化,它从每个局部区域中选择最大值作为输出,减小了特征图的尺寸并提高了计算效率。

全连接层通常位于网络的顶部,将卷积层和池化层提取的特征映射到输出类别。全连接层通过学习权重参数,将特征映射到每个类别的概率,最终实现图像分类。

激活层采用激活函数,把卷积层输出结果做非线性映射。在卷积层之后使用,以增加网络的表达能力。常见的激活函数包括ReLU(Rectified Linear Unit)、Sigmoid和Tanh等。ReLU是最常用的激活函数,它能够有效缓解梯度消失问题,并加速网络的收敛速度。

Softmax层通常作为网络的最后一层,用于将全连接层的输出转换成各个类别的概率分布。通过对这些概率进行比较,模型可以确定输入图像最可能属于哪个类别。

3 LeNet5网络基本架构

本实验使用CNN的经典模型LeNet5进行手写数字的识别。

LeNet-5的基本结构包括7层网络结构(不含输入层),其中包括2个卷积层、2个降采样层(池化层)、2个全连接层和输出层。

1)输入层(Input layer)

输入层接收大小为28×28 的手写数字图像,其中包括灰度值(0-255)。在本实验中对数据集进行预处理,数据进行了标准化,以加快训练速度和提高模型的准确性。[28,28,1]

2)卷积层C1(Convolutional layer C1)

卷积层C1包括6个卷积核,每个卷积核的大小为5×5,步长为1,填充为0。因此,每个卷积核会产生一个大小为28×28的特征图(输出通道数为6)。[28,28,6]

3)采样层S2(Subsampling layer S2)

采样层S2采用最大池化(max-pooling)操作,每个窗口的大小为2×2 ,步长为2。因此,每个池化操作会从4个相邻的特征图中选择最大值,产生一个大小为14×14的特征图(输出通道数为6)。[14,14,6]

4)卷积层C3(Convolutional layer C3)

卷积层C3包括16个卷积核,每个卷积核的大小为5×5 ,步长为1,填充为0。因此,每个卷积核会产生一个大小为10×10的特征图(输出通道数为16)。[10,10,16]

5)采样层S4(Subsampling layer S4)

采样层S4采用最大池化操作,每个窗口的大小为2×2,步长为2。因此,每个池化操作会从4个相邻的特征图中选择最大值,产生一个大小为5×5的特征图(输出通道数为16)。[5,5,16]

6)全连接层C5(Fully connected layer C5)

C5将每个大小为5×5 的特征图拉成一个长度为400的向量,并通过一个带有120个神经元的全连接层进行连接。120是由LeNet-5的设计者根据实验得到的最佳值。[400,]->[120,]

7)全连接层F6(Fully connected layer F6)

全连接层F6将120个神经元连接到84个神经元。[84,]

8)输出层(Output layer)

输出层由10个神经元组成,每个神经元对应0-9中的一个数字,并输出最终的分类结果。在训练过程中,使用交叉熵损失函数计算输出层的误差,并通过反向传播算法更新卷积核和全连接层的权重参数。[10,]

4 核心架构的具体实现

# 构建LeNet-5模型
model = models.Sequential([
    layers.Conv2D(6, kernel_size=(5, 5), strides=(1, 1), activation='relu', input_shape=(28, 28, 1), padding='same'),
    layers.AveragePooling2D(pool_size=(2, 2), strides=(2, 2), padding='valid'),
    layers.Conv2D(16, kernel_size=(5, 5), strides=(1, 1), activation='relu', padding='valid'),
    layers.AveragePooling2D(pool_size=(2, 2), strides=(2, 2), padding='valid'),
    layers.Flatten(),
    layers.Dense(120, activation='relu'),
    layers.Dense(84, activation='relu'),
    layers.Dense(10, activation='softmax')
])

# 编译模型
model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

# 训练模型
history = model.fit(train_images, train_labels, epochs=10, batch_size=16, validation_data=(test_images, test_labels))

5 网络训练和推理过程及说明

网络训练过程

·准备数据: 首先需要准备训练数据集和验证数据集。训练数据集通常用来训练模型的参数,验证数据集用来评估模型在训练过程中的性能。

·构建模型: 定义LeNet5模型的架构,包括输入层、隐藏层、输出层以及它们之间的连接关系。这里通过深度学习框架TensorFlow来实现。

·定义损失函数和优化器: 选择交叉熵作为损失函数和Adam作为优化器。

·训练模型: 将模型与训练数据集进行训练,通过反向传播算法不断优化模型参数,使得模型能够更好地拟合训练数据。

·评估模型: 使用验证数据集评估训练得到的模型的性能,观察模型在验证集上的表现,并根据评估结果进行调参和优化。

网络推理过程

·准备输入数据: 对于需要进行推理的新数据,首先需要进行预处理,使其能够输入到训练好的模型中进行推理。

·加载模型: 从保存的模型参数中加载训练好的模型。

·模型推理: 将输入数据通过加载的模型进行前向传播,得到模型的输出结果。

·输出结果

6 实验结果对比和分析

6.1 不同神经网络参数对性能的影响

通过对网络模型的不同参数的调整,发现以下几个参数都会对模型的性能产生影响:学习率、优化算法、激活函数、批处理大小。下面是不同的模型参数对模型准确率的影响

上图虽然数据过于多,但是很明显的一点是,当使用随机梯度下降(sgd)最为优化器,sigmoid作为激活函数的时候准确率尤其低,可以发现模型的参数选择非常重要,下面是对不同模型参数的的实验结果比对和研究。

6.1.1 批处理大小

在本次实验中,我们探究了不同批量大小对LeNet5模型性能的影响。我们使用了批量大小为16、32和64,并记录了每个批量大小下模型在测试集上的准确率。

由于有几个点的准确率过于低,使整个折现图不是很直观,于是将上述几个准确率过于低的点去掉,可以得到以下可视化折线图

我们可以明显地观察到,在不同的批量大小下,模型的准确率存在差异。具体来说,批量大小为64时,我们观察到最低的准确率。

一般而言,较大的批量大小可能会降低模型的收敛速度,而较小的批量大小可能导致模型更快地收敛但容易受到数据噪声的影响。这种差异可能是由于不同批量大小下梯度估计的差异所导致。

考虑到模型的性能在不同批量大小下存在明显变化,批量大小的选择在训练深度学习模型时至关重要。然而,并不存在一种适用于所有情况的通用最佳批量大小,因此在选择批量大小时需要综合考虑模型架构、数据集特性和优化器的选择。

综上所述,批量大小作为一个重要的超参数,对于模型的性能具有显著影响。在实践中,我们建议根据具体情况进行实验和验证,以确定最适合的批量大小,从而有效地训练深度学习模型。

6.1.2 学习率

学习率(learning rate)是训练神经网络时一个非常重要的超参数,它决定了模型在每次参数更新时的步长大小。学习率的选择对模型的性能有着直接的影响,过大或过小的学习率都可能导致训练不稳定或性能下降。

如果学习率设置过大,可能导致参数更新过大,从而使得模型在参数空间中跳动幅度过大,无法收敛到最优解,甚至可能导致训练过程中出现震荡或不稳定的情况。

相反,如果学习率设置过小,模型参数更新的步长会变得很小,导致训练过程收敛速度缓慢,需要更多的迭代次数才能达到收敛,从而增加训练时间。此外,学习率过小还容易使得模型陷入局部最优解而难以获得全局最优解。

有6.1.1 可以看出来当batch_size为16时模型性能比较好,下面只可视化batch_size为16时的模型性能

可以看出过大或过小的学习率都可能导致训练不稳定或性能下降。在模型训练时应该选择恰当的学习率。

​​​​​​​6.1.3 优化算法

优化算法在训练神经网络时起着至关重要的作用,它决定了模型参数的更新方式和速度。不同的优化算法对模型性能有着直接的影响。

SGD 是最常见的优化算法之一,然而在本实验中,在对MNIST数据集的分类中SGD表现则没有那么良好。

相比其他两个Adam和RMSprop这两个自适应学习率算法,SGD的表现可以说是非常差。

对于 MNIST 这样的任务,Adam 和 RMSprop 这类自适应学习率算法通常能够快速收敛并取得较好的性能。因为这些算法能够自动调整学习率,适应不同特征的分布和参数的尺度,从而更快地收敛到最优解。

综上所述,对于 MNIST 数据集的分类任务,自适应学习率算法(如 Adam 和 RMSprop)通常能够在收敛速度和性能上取得良好的平衡。然而,对于特定的模型架构和超参数设置,不同的优化算法可能会有着不同的表现。

6.1.4 激活函数

不同的激活函数(如ReLU、Sigmoid、Tanh等)在网络训练中会对梯度传播和稀疏表示等方面产生不同的影响。实验发现就对MNIST数据集的分类ReLU表现更为好。

由上述两个图可以看出SGD(随机梯度下降)与 Sigmoid 激活函数结合导致准确率极为低。尝试分析了一下原因:

1)梯度消失问题: Sigmoid 函数具有饱和性,其导数在 0 到 1 之间。在网络的反向传播过程中,当梯度反向传播到较深层时,这种饱和性可能导致梯度消失,使得深层网络参数无法有效地更新,难以学习到复杂的特征表示。

2)非线性表达受限: Sigmoid 函数并不是非常适合作为激活函数,因为它只覆盖了一小部分输入范围,导致网络的表达能力受到限制。相比之下,ReLU 或其变体可以更好地处理非线性关系,并且不容易出现梯度消失的问题。

3)输出分布偏移: Sigmoid 输出值的范围在 0 到 1 之间,但是在实际应用中,可能需要更广泛的输出分布。特别是对于 MNIST 数据集中的分类问题,期望的输出是 one-hot 编码,即输出节点应该尽可能地接近 0 或 1。Sigmoid 输出的值域不是最理想的,可能导致网络训练困难。

4)SGD 优化器的限制: SGD 是一种简单的优化器,可能无法快速收敛到全局最优解。在复杂的模型结构中,SGD 可能会受到局部最小值或者鞍点的影响。

6.2 实验结果的分析

通过上述调试参数,最终使用如下参数进行模型的训练和测试,得到实验结果如下:

activations = [ 'relu']

learning_rates = [0.001]

optimizers = [ 'adam']

batch_sizes = [16]

epochs = 10

可视化:

可以看出模型预测出错的图片,人眼也很难识别,可见模型的训练还是比较成功的。

7. 各种神经网络方法的优缺点

7.1多层感知机(MLP)

优点: ①简单易用,适用于一些简单的分类和回归任务。

②可以进行非线性映射,对一些非线性问题的建模能力较强。

缺点: ①处理图像、语音和自然语言处理等复杂任务的能力有限。

②受限于全连接结构,参数较多,容易过拟合。

7.2卷积神经网络(CNN)

优点: ①在图像处理领域表现出色,能够自动提取局部特征。

②参数共享和池化操作减少了模型的参数数量,降低了过拟合风险。

缺点: ①对位置平移和尺度变化敏感,需要大量数据进行训练以获得良好的泛化性能。

②不擅长处理序列数据,如文本和时间序列数据。

7.3 循环神经网络(RNN)

优点: ①适用于处理序列数据,能够捕捉时间上的依赖关系。

②可以处理不定长的输入序列,适用于自然语言处理等任务。

缺点: ①难以捕捉长距离的依赖关系,存在梯度消失和梯度爆炸问题。

②计算效率较低,难以并行化处理。

7.4 长短期记忆网络(LSTM)和门控循环单元(GRU)

优点: ①解决了传统RNN难以捕捉长距离依赖关系的问题。

②具有记忆单元和门控机制,能够更好地处理长序列任务。

缺点: ①参数较多,需要更多的数据来训练。

②计算成本较高,对硬件要求较高。

8.总结和讨论

在MNIST手写字符识别任务中,CNN(例如LeNet-5)模型表现出了较好的性能,能够有效地提取图像特征,获得较高的准确率。

参数调优对模型性能影响显著,如学习率、批处理大小、优化算法和激活函数等。具体调整这些参数能够显著地改变模型的收敛速度和准确率。

不同的优化算法和激活函数对模型性能有重要影响。自适应学习率算法(如Adam、RMSprop)和ReLU激活函数通常能在训练效率和性能上取得较好的平衡。

手写字符识别问题在现代深度学习中仍然是一个重要的研究领域,不同的模型和方法在实际应用中各有优劣。

还有一些对于手写字符识别问题未来的看法和建议:

探索更深层次、更复杂的网络结构,例如ResNet、Inception等,在保持计算效率的同时提高模型性能。

应用更多的数据增强技术和预处理方法,以增加数据集的多样性,提高模型的鲁棒性和泛化能力。

结合迁移学习的方法,利用预训练的模型,在手写字符识别问题上进行fine-tuning。同时,尝试模型融合等集成学习方法,提高模型性能。

随着技术的发展,探索如注意力机制、图神经网络等新技术在手写字符识别中的应用,以提高模型的表达能力。

总体而言,手写字符识别问题仍有许多待解决的挑战,需要进一步的研究和探索新的方法,以应对不同场景下的需求,并不断提升模型性能。

9.附录

基于LeNet5模型进行MNIST手写数字集的分类,实验完整代码

import tensorflow as tf

from tensorflow.keras import layers, models, datasets

import matplotlib.pyplot as plt



# 加载MNIST数据集

(train_images, train_labels), (test_images, test_labels) = datasets.mnist.load_data()

train_images = train_images.reshape((60000, 28, 28, 1)).astype('float32') / 255

test_images = test_images.reshape((10000, 28, 28, 1)).astype('float32') / 255



# 构建LeNet-5模型

model = models.Sequential([

    layers.Conv2D(6, kernel_size=(5, 5), strides=(1, 1), activation='relu', input_shape=(28, 28, 1), padding='same'),

    layers.AveragePooling2D(pool_size=(2, 2), strides=(2, 2), padding='valid'),

    layers.Conv2D(16, kernel_size=(5, 5), strides=(1, 1), activation='relu', padding='valid'),

    layers.AveragePooling2D(pool_size=(2, 2), strides=(2, 2), padding='valid'),

    layers.Flatten(),

    layers.Dense(120, activation='relu'),

    layers.Dense(84, activation='relu'),

    layers.Dense(10, activation='softmax')

])



# 编译模型

model.compile(optimizer='adam',

              loss='sparse_categorical_crossentropy',

              metrics=['accuracy'])



# 训练模型

history = model.fit(train_images, train_labels, epochs=10, batch_size=16, validation_data=(test_images, test_labels))



# 可视化训练过程

plt.plot(history.history['accuracy'], label='accuracy')

plt.plot(history.history['val_accuracy'], label = 'val_accuracy')

plt.xlabel('Epoch')

plt.ylabel('Accuracy')

plt.ylim([0, 1])

plt.legend(loc='lower right')

plt.show()





# 评估模型

test_loss, test_acc = model.evaluate(test_images, test_labels)

print('Test accuracy:', test_acc)



import numpy as np



# 使用训练好的模型对测试集进行预测

predictions = model.predict(test_images)

predicted_labels = np.argmax(predictions, axis=1)



# 找出预测正确和错误的样本

correct_indices = np.where(predicted_labels == test_labels)[0]

incorrect_indices = np.where(predicted_labels != test_labels)[0]



# 输出部分预测错误的样本

plt.figure(figsize=(10, 10))

for i, incorrect_idx in enumerate(incorrect_indices[:25]):

    plt.subplot(5, 5, i + 1)

    plt.imshow(test_images[incorrect_idx].reshape(28, 28), cmap='gray')

    plt.title(f"Predicted: {predicted_labels[incorrect_idx]}, True: {test_labels[incorrect_idx]}")

    plt.axis('off')

plt.tight_layout()

plt.show()



# 输出部分预测正确的样本

plt.figure(figsize=(10, 10))

for i, correct_idx in enumerate(correct_indices[:25]):

    plt.subplot(5, 5, i + 1)

    plt.imshow(test_images[correct_idx].reshape(28, 28), cmap='gray')

    plt.title(f"Predicted: {predicted_labels[correct_idx]}, True: {test_labels[correct_idx]}")

    plt.axis('off')

plt.tight_layout()

plt.show()





# 参数配置实验

activations = ['tanh', 'relu', 'sigmoid']

learning_rates = [0.01, 0.001, 0.0001]

optimizers = ['sgd', 'adam', 'rmsprop']

batch_sizes = [16, 32, 64]

epochs = 3  



results = []



for act in activations:

    for lr in learning_rates:

        for opt in optimizers:

            for batch_size in batch_sizes:

                model = build_lenet5_model(activation=act)

                model.compile(optimizer=opt, loss='sparse_categorical_crossentropy', metrics=['accuracy'])

                history = model.fit(train_images, train_labels, batch_size=batch_size, epochs=epochs, validation_data=(test_images, test_labels))

                val_accuracy = history.history['val_accuracy'][-1]  # 获取最终验证准确率

                results.append((act, lr, opt, batch_size, val_accuracy))



import csv





# 将结果保存到CSV文件

filename = 'experiment_results.csv'



with open(filename, mode='w', newline='') as file:

    writer = csv.writer(file)

    writer.writerow(['Activation', 'Learning Rate', 'Optimizer', 'Batch Size', 'Validation Accuracy'])

for result in results:



# 提取结果并进行可视化

labels = [f'{act} LR:{lr} Opt:{opt} Batch:{batch}' for act, lr, opt, batch, _ in results]

accuracy_values = [accuracy for _, _, _, _, accuracy in results]



# 创建条形图

plt.figure(figsize=(15, 8))

plt.bar(labels, accuracy_values, color='skyblue')



# 添加标题和标签

plt.title('Validation Accuracy for Different Hyperparameter Combinations and Batch Sizes')

plt.xlabel('Hyperparameters and Batch Sizes')

plt.ylabel('Validation Accuracy')

plt.xticks(rotation=45, ha='right')

plt.tight_layout()

plt.show()



import csv

import matplotlib.pyplot as plt



# 读取CSV文件数据

filename = 'experiment_results.csv'



with open(filename, mode='r') as file:

    reader = csv.reader(file)

    header = next(reader)  # 读取标题行

    data = [row for row in reader]  # 读取数据行



# 提取数据

batch_sizes = set(row[3] for row in data)

activation_types = set(row[0] for row in data)

learning_rates = set(row[1] for row in data)

optimizers = set(row[2] for row in data)



# 准备数据并过滤性能较差的数据点

batch_size_data = {}

threshold = 0.5  # 设定阈值

for batch_size in batch_sizes:

    accuracies = [float(row[4]) for row in data if row[3] == batch_size and float(row[4]) > threshold]

    batch_size_data[batch_size] = accuracies



# 绘制折线图

plt.figure(figsize=(10, 6))

for batch_size, accuracies in batch_size_data.items():

    # 根据batch_size筛选数据行

    filtered_data = [row for row in data if row[3] == batch_size and float(row[4]) > threshold]

    # 获取当前参数的值作为标签

    labels = [f'{row[0]}, {row[1]}, {row[2]}' for row in filtered_data]

    plt.plot(labels, accuracies, marker='o', label=f'Batch Size: {batch_size}')



# 设置图表属性

plt.title('Model Performance by Different Batch Sizes')

plt.xlabel('Model Parameters')

plt.ylabel('Validation Accuracy')

plt.xticks(rotation=90)  # 旋转X轴标签,以防止重叠

plt.legend()



# 显示图表

plt.tight_layout()

plt.show()

Ps:省略了一些重复的代码

文档完成于2023/12/14

编辑于2023/12/30

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

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

相关文章

基于metersphere和supper-jacoco 测试覆盖率落地实践

一、背景及目标 背景 1、技术研发流程为测试 提供冒烟用例-开发根据用例自测-提测-开始测试,这一套流程,但是中间开发是否真实执行冒烟,测试并不知晓,而且测试提供冒烟用例是否符合标准也没法进行量化 2、公司产品属于saas产品&…

从0开始界面设计师 Qt Designer

QT程序界面的 一个个窗口、控件,就是像上面那样用相应的代码创建出来的。 但是,把你的脑海里的界面,用代码直接写出来,是有些困难的。 很多时候,运行时呈现的样子,不是我们要的。我们经常还要修改代码调整界…

2023年的Android开发:演进之年

2023年的Android开发:演进之年 在2023年,安卓开发迎来了许多新功能和里程碑,让我们来看看其中的一些关键功能。 Jetpack Compose 1.5.7 Jetpack Compose是一个用于构建安卓用户界面的工具,从Jetpack Compose 1.0到Jetpack Comp…

GBASE南大通用-GBase 8s分片表操作 提升大数据处理性能

目录 一、GBase 8s分片表的优势 二、六种分片方法 轮转 1.轮转法 基于表达式分片 2.基本表达式 3.Mod运算表达式 4.Remainder关键字方式 5.List方式 6.interval 固定间隔 三、分片表的索引 1.创建索引的注意事项 2.detach索引替代delete功能展现 3.在现有分片表上增加一个新…

C语言之指针和数组

指针和数组虽然是不同的东西,但却有着千丝万缕的关系,下面就让我们逐一了解吧! 指针和数组 数组名原则上会被解释为指向该数组起始元素的指针。 也就是说。如果a是数组,那么表达式a的值就是a[0]的值,即与&a[0]一…

TikTok真题第9天 | 163.缺失的区间、1861.旋转箱子、2217.找到指定长度的回文数

163.缺失的区间 题目链接:163.missing-ranges 解法: 基本逻辑是,依次遍历nums中的所有的元素,判断这个元素(right)和上一个元素(left)的差值是否>2,如果是&#xf…

Cisco模拟器-跨交换机实现VLAN

计要求将两台相互连接的交换机上的VLAN号全局使用,技术上可以使用TRUNK技术的数据包标记功能来实现。 通过设计,可以对多台交换机进行整合,提高网络设备的利用率、降低网络工程的成本,同时也可以简化网络配置。 交换机0配置&…

【privateGPT】使用privateGPT训练您自己的LLM

了解如何在不向提供商公开您的私人数据的情况下训练您自己的语言模型 使用OpenAI的ChatGPT等公共人工智能服务的主要担忧之一是将您的私人数据暴露给提供商的风险。对于商业用途,这仍然是考虑采用人工智能技术的公司最大的担忧。 很多时候,你想创建自己…

.FileZilla的使用和主动模式被动模式介绍

FileZilla的使用和主动模式被动模式介绍 1.FileZilla的使用和主动模式被动模式介绍1.安装下载2.新建组和用户2.1打开后出现如下界面2.2点击编辑打开组这个选项2.3点击添加组以后,点击确认2.4输入组的名称,列如我输入的niyin2.5点击用户选项2.6像上面一样…

Winform RDLC报表(数据库连接、报表函数使用、动态表头)

文章目录 NuGet安装库数据库连接报表设计报表引用添加报表 数据集设计方法一手动添加方法二——连接数据库添加 关联报表与数据集表格数据与数据集数据设计表格格式、字体设计报表数据字段绑定 Winform 使用报表控件数据库填充数据集从数据库获取与数据源相同字段的数据 动态表…

关于求定积分的反函数的导数【认清原函数x变量和反函数x变量】

如图碰到该题该怎么解? 在纸上按①②③的顺序写出这个,其中①是最主要的 第②步和第③步就是在用反函数时要用到的逻辑思维,不是一起用的,你需要用②才去用②,你需要用③才去用③ 在纸上先写出第①步,即 其…

【Linux操作系统】探秘Linux奥秘:操作系统的入门与实战

🌈个人主页:Sarapines Programmer🔥 系列专栏:《操作系统实验室》🔖诗赋清音:柳垂轻絮拂人衣,心随风舞梦飞。 山川湖海皆可涉,勇者征途逐星辉。 目录 🪐1 初识Linux OS …

css实现一个斑马条纹动画,实现一个理发店门口的小转转,进度条动画同理!

css实现一个斑马条纹动画,实现一个理发店门口的小转转 前置基础知识 css背景background的重复渐变属性repeating-linear-gradient() 该属性类似于linear-gradient(),但他会在整个方向上重复渐变以覆盖整个容器 一、先写一个普通渐变例子linear-gradient() &…

leetcode贪心算法题总结(三)

本章目录 1.合并区间2.无重叠区间3.用最少数量的箭引爆气球4.整数替换5.俄罗斯套娃信封问题6.可被三整除的最大和7.距离相等的条形码8.重构字符串 1.合并区间 合并区间 class Solution { public:vector<vector<int>> merge(vector<vector<int>>&…

ZigBee案例笔记 - 无线点灯

文章目录 无线点灯实验概述工程关键字工程文件夹介绍Basic RF软件设计框图简单说明工程操作Basic RF启动流程Basic RF发送流程Basic RF接收流程 无线点灯案例无线点灯现象 无线点灯实验概述 ZigBee无线点灯实验&#xff08;即Basic RF工程&#xff09;&#xff0c;由TI公司提供…

第一讲:BeanFactory和ApplicationContext

BeanFactory和ApplicationContext 什么是BeanFactory 它是ApplicationContext的父接口它才是Spring的核心容器&#xff0c;主要的ApplicationContext实现都组合了它的功能 BeanFactory能做什么? 表面上看BeanFactory的主要方法只有getBean()&#xff0c;实际上控制反转、基…

Spring-5-切入点的高级使用

Spring提供了两个额外的Pointcut实现&#xff0c;分别是ComposablePointcut和ControlFlowPointcut,它们提供了所需的灵活性。 使用控制流切入点 由ControlFlowPointcut类实现的Spring控制流切入点类似于许多其他AOP实现中可用的cflow构造&#xff0c;尽管功能上没有那么强大。…

(self-supervised learning)Event Camera Data Pre-training

Publisher: ICCV 2023 MOTIVATION OF READING: 自监督学习、稀疏事件 NILM link: https://arxiv.org/pdf/2301.01928.pdf Code: GitHub - Yan98/Event-Camera-Data-Pre-training 1. Overview Contributions are summarized as follows: 1. A self-supervised framework f…

“产品经理必懂的关键术语“

产品经理是现代企业中非常重要的一个角色&#xff0c;他们负责制定产品策略、规划产品开发流程、管理产品质量和用户反馈等等。然而&#xff0c;对于产品经理来说&#xff0c;了解并掌握相关的专业术语是非常重要的。本篇文章会介绍一些产品经理需要掌握的专业术语&#xff0c;…

一篇文章掌握系统架构的演变和常见微服务框架

目录 前言 一、系统架构的演变 1、单体应用架构 优点&#xff1a; 缺点&#xff1a; 2、垂直应用架构 优点&#xff1a; 缺点&#xff1a; 3、分布式SOA架构 3.1 什么是SOA 3.2 SOA架构 优点&#xff1a; 缺点&#xff1a; 4、微服务架构 优点&#xff1a; 缺点…