基于BP神经网络对MNIST数据集检测识别(Pytorch,Tensorflow版本)

news2024/11/25 0:31:49

基于BP神经网络对MNIST数据集检测识别

  • 1.作者介绍
  • 2.基于BP神经网络对MNIST数据集检测识别
    • 2.1 BP神经网络介绍
    • 2.2 神经元模型
    • 2.3 激活函数
    • 2.4 BP神经网络基础架构
    • 2.5 BP神经网络正向传播反向传播
  • 3.基于BP神经网络对MNIST数据集检测识别实验
    • 3.1 MNIST数据集介绍
    • 3.2代码实现(Pytorch版本)
    • 3.3代码实现(TensorFlow版本)
  • 4. BP神经网络注意问题
    • 4.1 代码相关问题

1.作者介绍

任陇刚,男,西安工程大学电子信息学院,2022级研究生
研究方向:机器视觉与人工智能
电子邮件:1756769702@qq.com

张思怡,女,西安工程大学电子信息学院,2022级研究生,张宏伟人工智能课题组
研究方向:机器视觉与人工智能
电子邮件:981664791@qq.com

2.基于BP神经网络对MNIST数据集检测识别

2.1 BP神经网络介绍

首先从名称中可以看出,Bp神经网络可以分为两个部分,bp和神经网络。bp是 Back Propagation 的简写 ,意思是反向传播。BP网络能学习和存贮大量的输入-输出模式映射关系,而无需事前揭示描述这种映射关系的数学方程。它的学习规则是使用最速下降法,通过反向传播来不断调整网络的权值和阈值,使网络的误差平方和最小。其主要的特点是:信号是正向传播的,而误差是反向传播的。算法流程图如下:
在这里插入图片描述

2.2 神经元模型

每个神经元都接受来自其它神经元的输入信号,每个信号都通过一个带有权重的连接传递,神经元把这些信号加起来得到一个总输入值,然后将总输入值与神经元的阈值进行对比(模拟阈值电位),然后通过一个“激活函数”处理得到最终的输出(模拟细胞的激活),这个输出又会作为之后神经元的输入一层一层传递下去。神经元模型如下:
在这里插入图片描述

2.3 激活函数

引入激活函数的目的是在模型中引入非线性。如果没有激活函数(其实相当于激励函数是f(x) = x),那么无论你的神经网络有多少层,最终都是一个线性映射,那么网络的逼近能力就相当有限,单纯的线性映射无法解决线性不可分问题。正因为上面的原因,我们决定引入非线性函数作为激励函数,这样深层神经网络表达能力就更加强大
BP神经网络算法常用的激活函数:
1)Sigmoid(logistic),也称为S型生长曲线,函数在用于分类器时,效果更好。
在这里插入图片描述
在这里插入图片描述
2)Tanh函数(双曲正切函数),解决了logistic中心不为0的缺点,但依旧有梯度易消失的缺点。
在这里插入图片描述
在这里插入图片描述
3)relu函数是一个通用的激活函数,针对Sigmoid函数和tanh的缺点进行改进的,目前在大多数情况下使用
在这里插入图片描述
在这里插入图片描述

2.4 BP神经网络基础架构

BP网络由输入层、隐藏层、输出层组成
在这里插入图片描述
输入层:信息的输入端,是读入你输入的数据的
隐藏层:信息的处理端,可以设置这个隐藏层的层数(在这里一层隐藏层,q个神经元)
输出层:信息的输出端,也就是我们要的结果
对于上图的只含一个隐藏层的神经网络模型:BP神经网络的过程主要分为两个阶段,
第一阶段是信号的正向传播,从输入层经过隐含层,最后到达输出层;
第二阶段是误差的反向传播,从输出层到隐含层,最后到输入层,依次调节隐含层到输出层的权重和偏置,输入层到隐含层的权重和偏置

2.5 BP神经网络正向传播反向传播

正向传播过程
正向传播就是让信息从输入层进入网络,依次经过每一层的计算,得到最终输出层结果的过程
从输入层到隐藏层:
从隐藏层到输出层:
以y1举例。y1里的输出自然有来自b1,b2,…bq的。那么分别按照权重去乘。

类似的我们可以求解出y2……yn
反向传播过程
基本思想就是通过计算输出层与期望值之间的误差来调整网络参数,从而使得误差变小。
计算误差公式如下:(差值的平方)
在这里插入图片描述
如何调整权重的大小,才能使损失函数不断地变小呢?
1.梯度下降法
2.(随机梯度下降)SGD
3.(自适应优化)Adam

3.基于BP神经网络对MNIST数据集检测识别实验

3.1 MNIST数据集介绍

MNIST 数据集可在 http://yann.lecun.com/exdb/mnist/ 获取,它包含了四个部分:
•Training set images: train-images-idx3-ubyte.gz (9.9 MB, 解压后 47 MB, 包含 60,000 个样本)
•Training set labels: train-labels-idx1-ubyte.gz (29 KB, 解压后 60 KB, 包含 60,000 个标签)
•Test set images: t10k-images-idx3-ubyte.gz (1.6 MB, 解压后 7.8 MB, 包含 10,000 个样本)
•Test set labels: t10k-labels-idx1-ubyte.gz (5KB, 解压后 10 KB, 包含 10,000 个标签)
Mnist数据集中的标签是介于0~9的数字,Mnist中的标签是用独热编码(one-hot-vectors)表示的,一个one-hot向量除了某一位数字是1以外,其余维度的数组都是0,比如标签0用独热编码表示为([1, 0, 0, 0, 0, 0, 0, 0, 0, 0]),标签3用独热编码表示为([0, 0, 0, 1, 0, 0, 0, 0, 0, 0])。所以,Mnist数据集中所有的标签mnist.train.labels是一个[60000, 10]的数字矩阵。
在这里插入图片描述
训练图片和测试图片:
每一张图片包含2828个像素。Mnist数据集把代表一张图片的二维数据转开成一个向量,长度为2828=784。因此在Mnist的训练数据集中mnist.train.images是一个形状为[60000, 784]的张量,第一个维度数字用来索引图片,第二个维度数字用来索引每张图片中的像素点,图片里的某个像素的强度值介于0-1之间。(图8部分数据可视化)
在这里插入图片描述
在这里插入图片描述

3.2代码实现(Pytorch版本)

定义transform对象,其定义了数据集中的图片应该做怎样的处理:

transform = transforms.Compose([transforms.ToTensor(),
                                transforms.Normalize((0.5,), (0.5,)), ])

加载和下载训练测试数据集,这里使用pytorch提供的API进行下载:

train_set = datasets.MNIST('data',  # 下载到该文件夹下
                           download=not os.path.exists('train_set'),  # 是否下载,如果下载过,则不重复下载
                           train=True,  # 是否为训练集
                           transform=transform  # 要对图片做的transform
                           )
print(train_set)
test_set = datasets.MNIST('data',
                          download=not os.path.exists('test_set'),
                          train=False,
                          transform=transform
                          )
print(test_set)

构建训练数据集和测试数据集的DataLoader对象:

train_loader = torch.utils.data.DataLoader(train_set, batch_size=128, shuffle=True)
test_loader = torch.utils.data.DataLoader(test_set, batch_size=128, shuffle=True)

dataiter = iter(train_loader)
images, labels = dataiter.next()

print(images.shape)
print(labels.shape)

在上面,batch_size=64,每个batch送进64张图片每个图片只有一个通道(灰度图),大小为28x28。抽一张绘制一下:

plt.imshow(images[0].numpy().squeeze(), cmap='gray_r');

定义神经网络:

class NerualNetwork(nn.Module):
    def __init__(self):
        super().__init__()
        """
        定义第一个线性层,
        输入为图片(28x28),
        输出为第一个隐层的输入,大小为128。
        """
        self.linear1 = nn.Linear(28 * 28, 128)
        # 在第一个隐层使用ReLU激活函数
        self.relu1 = nn.ReLU()
        """
        定义第二个线性层,
        输入是第一个隐层的输出,
        输出为第二个隐层的输入,大小为64。
        """
        self.linear2 = nn.Linear(128, 64)
        # 在第二个隐层使用ReLU激活函数
        self.relu2 = nn.ReLU()
        """
        定义第三个线性层,
        输入是第二个隐层的输出,
        输出为输出层,大小为10
        """
        self.linear3 = nn.Linear(64, 10)
        # 最终的输出经过softmax进行归一化
        self.softmax = nn.LogSoftmax(dim=1)

        # 上述操作可以直接使用nn.Sequential写成如下形式:
        self.model = nn.Sequential(nn.Linear(28 * 28, 128),
                                   nn.ReLU(),
                                   nn.Linear(128, 64),
                                   nn.ReLU(),
                                   nn.Linear(64, 10),
                                   nn.LogSoftmax(dim=1)
                                   )

网络前向传播

def forward(self, x):
    """
    定义神经网络的前向传播
    x: 图片数据, shape为(64, 1, 28, 28)
    """
    # 首先将x的shape转为(64, 784)
    x = x.view(x.shape[0], -1)
    # 接下来进行前向传播
    x = self.linear1(x)
    x = self.relu1(x)
    x = self.linear2(x)
    x = self.relu2(x)
    x = self.linear3(x)
    x = self.softmax(x)
    # 上述一串,可以直接使用 x = self.model(x) 代替。
    return x

模型实例化:
定义损失函数,这里选用负对数似然损失函数(NLLLoss, negative log likelihood loss),其常用于分类任务
定义优化器,这里使用随机梯度下降法,学习率设置为0.003,momentum取默认的0.9(用于防止过拟合)

model = NerualNetwork()
criterion = nn.NLLLoss()
optimizer = optim.SGD(model.parameters(), lr=0.003, momentum=0.9)

模型训练过程:

time0 = time()  # 记录下当前时间
epochs = 15  # 一共训练15轮
for e in range(epochs):
    running_loss = 0  # 本轮的损失值
    for images, labels in train_loader:
        # 前向传播获取预测值
        output = model(images)
        # 计算损失
        loss = criterion(output, labels)
        # 进行反向传播
        loss.backward()
        # 更新权重
        optimizer.step()
        # 清空梯度
        optimizer.zero_grad()
        # 累加损失
        running_loss += loss.item()
    else:
        # 一轮循环结束后打印本轮的损失函数
        print("Epoch {} - Training loss: {}".format(e+1, running_loss / len(train_loader)))
# 打印总的训练时间
print("\nTraining Time (in minutes) =", (time() - time0) / 60)


correct_count, all_count = 0, 0
model.eval()  # 将模型设置为评估模式
# 从test_loader中一批一批加载图片
for images, labels in test_loader:
    # 循环检测这一批图片
    for i in range(len(labels)):
        logps = model(images[i])  # 进行前向传播,获取预测值
        probab = list(logps.detach().numpy()[0])                        # 将预测结果转为概率列表。[0]是取第一张照片的10个数字的概率列表(因为一次只预测一张照片)
        pred_label = probab.index(max(probab))  # 取最大的index作为预测结果
        true_label = labels.numpy()[i]
        if (true_label == pred_label):  # 判断是否预测正确
            correct_count += 1
        all_count += 1

print("Number Of Images Tested =", all_count)
print("\nModel Accuracy ={}%".format((correct_count / all_count)*100))

完整代码:

import os
import numpy as np
import torch
import torchvision
import matplotlib.pyplot as plt
from time import time
from torchvision import datasets, transforms
from torch import nn, optim

transform = transforms.Compose([transforms.ToTensor(),
                                transforms.Normalize((0.5,), (0.5,)), ])

train_set = datasets.MNIST('data',  # 下载到该文件夹下
                           download=not os.path.exists('train_set'),  # 是否下载,如果下载过,则不重复下载
                           train=True,  # 是否为训练集
                           transform=transform  # 要对图片做的transform
                           )
print(train_set)
test_set = datasets.MNIST('data',
                          download=not os.path.exists('test_set'),
                          train=False,
                          transform=transform
                          )
print(test_set)
train_loader = torch.utils.data.DataLoader(train_set, batch_size=128, shuffle=True)
test_loader = torch.utils.data.DataLoader(test_set, batch_size=128, shuffle=True)

dataiter = iter(train_loader)
images, labels = dataiter.next()

print(images.shape)
print(labels.shape)

plt.imshow(images[0].numpy().squeeze(), cmap='gray_r');


class NerualNetwork(nn.Module):
    def __init__(self):
        super().__init__()
        """
        定义第一个线性层,
        输入为图片(28x28),
        输出为第一个隐层的输入,大小为128。
        """
        self.linear1 = nn.Linear(28 * 28, 128)
        # 在第一个隐层使用ReLU激活函数
        self.relu1 = nn.ReLU()
        """
        定义第二个线性层,
        输入是第一个隐层的输出,
        输出为第二个隐层的输入,大小为64。
        """
        self.linear2 = nn.Linear(128, 64)
        # 在第二个隐层使用ReLU激活函数
        self.relu2 = nn.ReLU()
        """
        定义第三个线性层,
        输入是第二个隐层的输出,
        输出为输出层,大小为10
        """
        self.linear3 = nn.Linear(64, 10)
        # 最终的输出经过softmax进行归一化
        self.softmax = nn.LogSoftmax(dim=1)

        # 上述操作可以直接使用nn.Sequential写成如下形式:
        self.model = nn.Sequential(nn.Linear(28 * 28, 128),
                                   nn.ReLU(),
                                   nn.Linear(128, 64),
                                   nn.ReLU(),
                                   nn.Linear(64, 10),
                                   nn.LogSoftmax(dim=1)
                                   )

    def forward(self, x):
        """
        定义神经网络的前向传播
        x: 图片数据, shape为(64, 1, 28, 28)
        """
        # 首先将x的shape转为(64, 784)
        x = x.view(x.shape[0], -1)
        # 接下来进行前向传播
        x = self.linear1(x)
        x = self.relu1(x)
        x = self.linear2(x)
        x = self.relu2(x)
        x = self.linear3(x)
        x = self.softmax(x)
        # 上述一串,可以直接使用 x = self.model(x) 代替。
        return x


model = NerualNetwork()
criterion = nn.NLLLoss()
optimizer = optim.SGD(model.parameters(), lr=0.003, momentum=0.9)

time0 = time()  # 记录下当前时间
epochs = 15  # 一共训练15轮
for e in range(epochs):
    running_loss = 0  # 本轮的损失值
    for images, labels in train_loader:
        # 前向传播获取预测值
        output = model(images)
        # 计算损失
        loss = criterion(output, labels)
        # 进行反向传播
        loss.backward()
        # 更新权重
        optimizer.step()
        # 清空梯度
        optimizer.zero_grad()
        # 累加损失
        running_loss += loss.item()
    else:
        # 一轮循环结束后打印本轮的损失函数
        print("Epoch {} - Training loss: {}".format(e+1, running_loss / len(train_loader)))
# 打印总的训练时间
print("\nTraining Time (in minutes) =", (time() - time0) / 60)


correct_count, all_count = 0, 0
model.eval()  # 将模型设置为评估模式
# 从test_loader中一批一批加载图片
for images, labels in test_loader:
    # 循环检测这一批图片
    for i in range(len(labels)):
        logps = model(images[i])  # 进行前向传播,获取预测值
        probab = list(logps.detach().numpy()[0])                        # 将预测结果转为概率列表。[0]是取第一张照片的10个数字的概率列表(因为一次只预测一张照片)
        pred_label = probab.index(max(probab))  # 取最大的index作为预测结果
        true_label = labels.numpy()[i]
        if (true_label == pred_label):  # 判断是否预测正确
            correct_count += 1
        all_count += 1

print("Number Of Images Tested =", all_count)
print("\nModel Accuracy ={}%".format((correct_count / all_count)*100))

3.3代码实现(TensorFlow版本)

加载数据

#加载数据
mnist = tf.keras.datasets.mnist
(train_x,train_y),(test_x,test_y) = mnist.load_data()
print('\n train_x:%s, train_y:%s, test_x:%s, test_y:%s'%(train_x.shape,train_y.shape,test_x.shape,test_y.shape))

数据预处理

#归一化、并转换为tensor张量,数据类型为float32.
X_train,X_test = tf.cast(train_x/255.0,tf.float32),tf.cast(test_x/255.0,tf.float32)
y_train,y_test = tf.cast(train_y,tf.int16),tf.cast(test_y,tf.int16)

建立模型(单层隐含层的神经网络)

#建立模型
model = tf.keras.Sequential()
model.add(tf.keras.layers.Flatten(input_shape=(28,28)))     #添加Flatten层说明输入数据的形状
model.add(tf.keras.layers.Dense(128,activation='relu'))     #添加隐含层,为全连接层,128个节点,relu激活函数
model.add(tf.keras.layers.Dense(10,activation='softmax'))   #添加输出层,为全连接层,10个节点,softmax激活函数
print('\n',model.summary())     #查看网络结构和参数信息

配置模型训练方法

#配置模型训练方法
#adam算法参数采用keras默认的公开参数,损失函数采用稀疏交叉熵损失函数,准确率采用稀疏分类准确率函数
model.compile(optimizer='adam',loss='sparse_categorical_crossentropy',metrics=['sparse_categorical_accuracy'])

评估模型

#评估模型
model.evaluate(X_test,y_test,verbose=2)    #每次迭代输出一条记录,来评价该模型是否有比较好的泛化能力

保存模型

#保存整个模型
model.save('mnist_weights.h5')

结果可视化

#结果可视化
print(history.history)
loss = history.history['loss']          #训练集损失
val_loss = history.history['val_loss']  #测试集损失
acc = history.history['sparse_categorical_accuracy']            #训练集准确率
val_acc = history.history['val_sparse_categorical_accuracy']    #测试集准确率

运行结果
在这里插入图片描述
测试结果
在这里插入图片描述
在这里插入图片描述
完整代码:

########手写数字数据集##########
###########保存模型############
########1层隐含层(全连接层)##########
#60000条训练数据和10000条测试数据,28x28像素的灰度图像
#隐含层激活函数:ReLU函数
#输出层激活函数:softmax函数(实现多分类)
#损失函数:稀疏交叉熵损失函数
#输入层有784个节点,隐含层有128个神经元,输出层有10个节点
import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np

import time
print('--------------')
nowtime = time.strftime('%Y-%m-%d %H:%M:%S')
print(nowtime)

#指定GPU
import os
os.environ["CUDA_VISIBLE_DEVICES"] = "0"
# gpus = tf.config.experimental.list_physical_devices('GPU')
# tf.config.experimental.set_memory_growth(gpus[0],True)
#初始化
plt.rcParams['font.sans-serif'] = ['SimHei']

#加载数据
mnist = tf.keras.datasets.mnist
(train_x,train_y),(test_x,test_y) = mnist.load_data()
print('\n train_x:%s, train_y:%s, test_x:%s, test_y:%s'%(train_x.shape,train_y.shape,test_x.shape,test_y.shape))

#数据预处理
#X_train = train_x.reshape((60000,28*28))
#Y_train = train_y.reshape((60000,28*28))       #后面采用tf.keras.layers.Flatten()改变数组形状

#归一化、并转换为tensor张量,数据类型为float32.
X_train,X_test = tf.cast(train_x/255.0,tf.float32),tf.cast(test_x/255.0,tf.float32)
y_train,y_test = tf.cast(train_y,tf.int16),tf.cast(test_y,tf.int16)

#建立模型
model = tf.keras.Sequential()
model.add(tf.keras.layers.Flatten(input_shape=(28,28)))     #添加Flatten层说明输入数据的形状
model.add(tf.keras.layers.Dense(128,activation='relu'))     #添加隐含层,为全连接层,128个节点,relu激活函数
model.add(tf.keras.layers.Dense(10,activation='softmax'))   #添加输出层,为全连接层,10个节点,softmax激活函数
print('\n',model.summary())     #查看网络结构和参数信息

#配置模型训练方法
#adam算法参数采用keras默认的公开参数,损失函数采用稀疏交叉熵损失函数,准确率采用稀疏分类准确率函数
model.compile(optimizer='adam',loss='sparse_categorical_crossentropy',metrics=['sparse_categorical_accuracy'])

#训练模型
#批量训练大小为64,迭代5次,测试集比例0.2(48000条训练集数据,12000条测试集数据)
print('--------------')
nowtime = time.strftime('%Y-%m-%d %H:%M:%S')
print('训练前时刻:'+str(nowtime))

history = model.fit(X_train,y_train,batch_size=64,epochs=30,validation_split=0.2)

print('--------------')
nowtime = time.strftime('%Y-%m-%d %H:%M:%S')
print('训练后时刻:'+str(nowtime))
#评估模型
model.evaluate(X_test,y_test,verbose=2)    #每次迭代输出一条记录,来评价该模型是否有比较好的泛化能力

#保存模型参数
#model.save_weights('C:\\Users\\xuyansong\\Desktop\\深度学习\\python\\MNIST\\模型参数\\mnist_weights.h5')
#保存整个模型
model.save('mnist_weights.h5')


#结果可视化
print(history.history)
loss = history.history['loss']          #训练集损失
val_loss = history.history['val_loss']  #测试集损失
acc = history.history['sparse_categorical_accuracy']            #训练集准确率
val_acc = history.history['val_sparse_categorical_accuracy']    #测试集准确率

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

plt.subplot(121)
plt.plot(loss,color='b',label='train')
plt.plot(val_loss,color='r',label='test')
plt.ylabel('loss')
plt.legend()

plt.subplot(122)
plt.plot(acc,color='b',label='train')
plt.plot(val_acc,color='r',label='test')
plt.ylabel('Accuracy')
plt.legend()

#暂停5秒关闭画布,否则画布一直打开的同时,会持续占用GPU内存
#根据需要自行选择
#plt.ion()       #打开交互式操作模式
#plt.show()
#plt.pause(5)
#plt.close()

#使用模型
plt.figure()
for i in range(10):
    num = np.random.randint(1,10000)

    plt.subplot(2,5,i+1)
    plt.axis('off')
    plt.imshow(test_x[num],cmap='gray')
    demo = tf.reshape(X_test[num],(1,28,28))
    y_pred = np.argmax(model.predict(demo))
    plt.title('标签值:'+str(test_y[num])+'\n预测值:'+str(y_pred))
y_pred = np.argmax(model.predict(X_test[0:5]),axis=1)
print('X_test[0:5]: %s'%(X_test[0:5].shape))
print('y_pred: %s'%(y_pred))

plt.ion()       #打开交互式操作模式
plt.show()
plt.pause(5)
plt.close()

4. BP神经网络注意问题

a)参数选取很重要。 用最基本的BP 算法来训练BP 神经网络时,学习率、均方误差、权值、阈值的设置都对网络的训练均有影响。综合选取合理的值,将有利于网络的训练。在最基本的BP 算法中,学习率在整个训练过程是保持不变的,学习率过大,算法可能振荡而不稳定;学习率过小,则收敛速度慢,训练时间长。
b)存在麻痹现象。由于优化的目标函数很复杂,它必然会在神经元输出接近0或1的情况下,出现一些平坦区,在这些区域内,权值误差改变很小,使训练过程几乎停顿;
c) 搜索步长提前确定。 为了使网络执行BP算法,不能用传统的一维搜索法求每次迭代的步长,而必须把步长的更新规则预先赋予网络,这种方法将引起算法低效。
不同epoch下的Accurary可视化结果:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4.1 代码相关问题

Dataloader中num_worker设置
在这里插入图片描述
在这里插入图片描述
•num_workers=0表示只有主进程去加载batch数据,这个可能会是一个瓶颈。
•num_workers = 1表示只有一个worker进程用来加载batch数据,而主进程是不参与数据加载的。这样速度也会很慢。
•num_workers>0 表示只有指定数量的worker进程去加载数据,主进程不参与。增加num_works也同时会增加cpu内存的消耗。所以num_workers的值依赖于 batch size和机器性能。
•一般开始是将num_workers设置为等于计算机上的CPU数量
•最好的办法是缓慢增加num_workers,直到训练速度不再提高,就停止增加num_workers的值。

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

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

相关文章

Playwright系列:第14章 Playwright性能测试实战

下方查看历史精选文章 重磅发布 - 自动化框架基础指南pdfv1.1大数据测试过程、策略及挑战 测试框架原理,构建成功的基石 在自动化测试工作之前,你应该知道的10条建议 在自动化测试中,重要的不是工具 功能测试可以验证应用程序的功能是否正常,…

Cocos Store打通企业提现,诚邀更多团队和公司入驻!

2023年5月29日 Cocos Store 终于上线,令众多开发者期盼已久的功能——企业对公提现。 在此,真诚地对大家说一声:抱歉,我们来晚了! 但请一定相信 Cocos 引擎、Cocos Store 一直在努力并从未间断为开发者们创造价值&…

chatgpt赋能python:小黑框:Python程序员必备利器

小黑框:Python程序员必备利器 如果您是一名Python程序员,小黑框(Terminal)一定不陌生。小黑框是一种基于文本的用户界面,通常用于执行命令行任务,编写或调试代码等。Python程序员可以通过小黑框完成许多任…

【JUC基础】16. Fork Join

1、前言 “分而治之”一直是一个非常有效的处理大量数据的方法。著名的MapReduce也是采取了分而治之的思想。。简单地说,就是如果你要处理 1000 个数据,但是你并不具备处理 1000个数据的能力,那么你可以只处理其中的 10 个,然后分…

使用JSAPl来做一个倒计时的效果

今天的小案例需要做一个倒计时的效果 我们的时分秒需要一直进行倒计时&#xff0c;然后我们的页面颜色需要根据定时器的操作来进行更换&#xff0c;首先我们还是可以来分析一下我们的HTML步骤 <div class"countdown"><p class"next">今天是22…

HCIE-Cloud Computing LAB备考第二步:实战解题–第五题:论述二--跨数据中心部署问答--缩写法

跨数据中心部署 通常部署在同城或相近城市存在的两个数据中心&#xff0c;其物理距离在300km以内&#xff0c;两个数据中心均处于运行状态&#xff0c;可同时承担相同业务&#xff0c;提高数据中心的整体服务能力和系统资源利用率&#xff0c;当单数据中心故障时&#xff0c;业…

学会使用perf性能分析工具(含移植到arm-linux开发板)

文章目录 一、在ubuntu中使用apt包下载Perf二、使用源码安装Perf&#xff0c;并移植到arm-linux环境下三、使用perf四、Perf的功能介绍 系统&#xff1a;Ubuntu18.04系统 内核版本&#xff1a;5.4.0-150-generic&#xff08;通过uname -r查看&#xff09; 一、在ubuntu中使用ap…

针对大屏设备优化 Android 应用的方式及相关注意事项

作者 / Android 团队 近年来&#xff0c;包括大型可折叠设备、平板电脑以及 Chromebook 等大屏 Android 设备的数量与日俱增。确保应用可以在大屏设备上为用户提供无缝体验比以往任何时候都更加重要。例如&#xff0c;用户希望应用能够更充分利用这些设备的更大屏幕空间。我们发…

数据库信息速递 MONGODB CTO 看数据库发展趋势 与 不使用MONGODB你就要交“创新税”...

开头还是介绍一下群&#xff0c;如果感兴趣polardb ,mongodb ,mysql ,postgresql ,redis 等有问题&#xff0c;有需求都可以加群群内有各大数据库行业大咖&#xff0c;CTO&#xff0c;可以解决你的问题。加群请联系 liuaustin3 &#xff0c;在新加的朋友会分到2群 3群&#xff…

为了女神,我拼了!

大家注意&#xff1a;因为微信最近又改了推送机制&#xff0c;经常有小伙伴说错过了之前被删的文章&#xff0c;比如前阵子冒着风险写的爬虫&#xff0c;再比如一些限时福利&#xff0c;错过了就是错过了。 所以建议大家加个星标&#xff0c;就能第一时间收到推送。&#x1f44…

第二十八章 开发Productions - ObjectScript Productions - 定义业务操作

文章目录 第二十八章 开发Productions - ObjectScript Productions - 定义业务操作介绍关键原则定义业务操作类 第二十八章 开发Productions - ObjectScript Productions - 定义业务操作 本页介绍如何定义业务操作类。 提示&#xff1a; IRIS 提供使用特定出站适配器的专用业…

解读大模型的微调

在快速发展的人工智能领域中&#xff0c;有效地利用大型语言模型&#xff08;LLM&#xff09;变得越来越重要。然而&#xff0c;有许多不同的方式可以使用大型语言模型&#xff0c;这可能会让我们感到困惑。实际上&#xff0c;可以使用预训练的大型语言模型进行新任务的上下文学…

【移动架构】Flutter和React Native:最后的PK

首先&#xff0c;有点离题。做出决定的最简单方法是回顾历史。让我们沿着怀旧之路走一趟。早在2000年初&#xff0c;JAVA就有两个UI框架。一个是AWT&#xff0c;它是一种为多个操作系统构建UI的方法&#xff0c;同时仍然保持操作系统的外观。 每个操作系统都有自己的组件&#…

驱动开发--创建设备文件--控制LED灯

目录 1、手动创建设备文件 2、应用程序如何将数据传递给驱动 3、控制LED灯&#xff1a; 4、应用层控制灯 5、自动创建设备节点 1、手动创建设备文件 cat /proc/devices 查看主设备号 sudo mknod hello(路径&#xff1a;任意的) c/b&#xff08;C代表字符设备 b代表块设备&a…

华为无线AC双机热备三层组网配置案例

核心交换机: dis current-configuration sysname hx undo info-center enable vlan batch 10 66 88 99 to 100 ip pool vlan10 gateway-list 192.168.10.254 network 192.168.10.0 mask 255.255.255.0 dns-list 8.8.8.8 ip pool vlan100 gateway-list 172.16.100.254 network …

Qt在MySQL中存储音频文件

一、在存储音频视频等大文件时需要以二进制文件进行存储&#xff0c;首先需要了解mysql存储二进制文件的字段类型以及大小&#xff1a; 需要创建数据库中的图片类型为&#xff1a;二进制mediumblob类型&#xff0c;&#xff08; TinyBlob 最大 255 Blob 最大 65K MediumBlob …

苹果发布会,卧槽,卧槽,卧槽

今天跟二哥在群里聊到苹果的发布会&#xff0c;二哥完整的看了发布会&#xff0c;我随口问一句二哥看完后什么感受。 二哥说「苹果的工业设计还是遥遥领先&#xff0c;交互设计也是一流水准&#xff0c;然后价格也是遥遥领先」。 然后&#xff0c;我今天也抽空看了关于苹果新发…

【算法与数据结构】203、LeetCode移除链表元素

文章目录 题目一、解题思路完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 题目 一、解题思路 思路分析&#xff1a;这道题需要注意一个特殊情况&#xff0c;当删除的是头结点时&#xff0c;直接删除就找不到整个链表。因此我…

2023LRC软件、Adobe Lightroom Classic下载、安装教程

最后附下载地址 LRC简介&#xff1a; Adobe Lightroom Classic&#xff08;简称LR&#xff09;是Adobe Creative Cloud大家庭中的一款专业的图片管理和编辑工具&#xff0c;用于专业摄影师、摄影爱好者以及所有不断优化数码影像的人等。其目标是以丰富的功能提供高效、一致的…

03【WebStorm开发工具】

上一篇&#xff1a;02【HTML快速入门】 下一篇&#xff1a;04【】 目录&#xff1a;【HTML5系列教程】 文章目录 三、WebStorm开发工具3.1 WebStorm简介3.2 WebStorm安装3.3 WebStorm基本使用3.3.1 创建项目3.3.2 调整字体大小3.3.3 代码自动补全3.3.4 WebStorm常用快捷键 三…