当前位置: 首页 > news >正文

前馈神经网络与支持向量机实战 --- 手写数字识别

前馈神经网络与支持向量机实战 — 手写数字识别

文章目录

  • 前馈神经网络与支持向量机实战 --- 手写数字识别
    • 一、前馈神经网络介绍
    • 二、支持向量机介绍
    • 三、数据集说明
    • 四、环境准备
    • 五、实验要求
    • 六、Python代码
        • tutorial_minst_fnn-keras.py:使用TensorFlow的Sequential实现的前馈神经网络
        • tutorial_minst_fnn-tf2.0.py:使用TensorFlow的基础功能实现前馈神经网络
        • SVM_sklearn.py:使用sk-learn实现支持向量机
        • tutorial_minst_fnn-numpy.py:手写实现前馈神经网络(仅使用numpy,包括手写反向传播算法求解过程)
        • SVM_manual.py:手写支持向量机(包括支持向量机的优化算法——SMO算法)
    • 七、实验结果分析

一、前馈神经网络介绍

前馈神经网络(feedforward neural network,FNN),是一种最简单的神经网络,各神经元分层排列,每个神经元只与前一层的神经元相连。接收前一层的输出,并输出给下一层,各层间没有反馈,信号从输入层向输出层单向传播。

前馈神经网络采用一种单向多层结构。其中每一层包含若干个神经元。在此种神经网络中,各神经元可以接收前一层神经元的信号,并产生输出到下一层。第0层叫输入层,最后一层叫输出层,其他中间层叫做隐含层(或隐藏层、隐层)。隐层可以是一层。也可以是多层 。

一个典型的多层前馈神经网络如下图所示:

在这里插入图片描述

对于前馈神经网络结构设计,通常采用的方法有3类:直接定型法、修剪法和生长法。

关于神经网络的知识其实很多,这里也不展开进行叙述了.

⭐⭐⭐⭐⭐推荐参考书籍: 神经网络与深度学习nndl-book .

(邱锡鹏教授的《神经网络与深度学习》一书较全面地介绍了神经网络、机器 学习和深度学习的基本概念、模型和方法,同时也涉及深度学习中许多最新进 展.书后还提供了相关数学分支的简要介绍,以供读者需要时参考)

二、支持向量机介绍

支持向量机(Support Vector Machine, SVM)是一类按监督学习(supervised learning)方式对数据进行二分类的广义线性分类器(generalized linear classifier),其决策边界是对学习样本求解的最大边距超平面(maximum-margin hyperplane)

简单来说, 支持向量机(SVM)是一种求解二分类问题的算法,其核心思想为使用一线 性超平面将两类样本分开并使得两类样本与该超平面间的“间隔”最大。

对于非线性可分(无法找到可将两类样本分开的超平面)的样本集。SVM 采用核技巧将样本映射到更高维的空间上。已经证明,存在原样本空间到希尔伯特 空间的一个映射,使样本线性可分。

对于𝑛分类(𝑛 > 2)的问题,可以采用训练多个 SVM 的方式解决,其中常用的方法有:

  • 一类 VS 其它类(OVR)

    即: 训练𝑛 − 1个 SVM,第𝑖个 SVM 用于分类是第𝑖个类别还是其它类别。

  • 一类 VS 另一类(OVO)

    即: 对任意两个类别都训练一个 SVM,共需𝐶n 2个分类器,一个样本将通过所有分类器,最终将样本决策为结果最多的类别。

在这里插入图片描述

同样,过多的深入的内容也不在此进行赘述了,感兴趣的可参考以下文章:

机器学习:支持向量机(SVM)

【数之道】支持向量机SVM是什么,八分钟直觉理解其本质

【机器学习】支持向量机 SVM

三、数据集说明

MNIST数据集(Mixed National Institute of Standards and Technology database)是美国国家标准与技术研究院收集整理的大型手写数字数据库,是机器学习领域中非常经典的一个数据集,由60000个训练样本和10000个测试样本组成,每个样本都是一张28 * 28像素的灰度手写数字图片。

  • 官方网站 http://yann.lecun.com/exdb/mnist/
  • 一共4个文件,训练集、训练集标签、测试集、测试集标签
文件名称大小内容
train-images-idx3-ubyte.gz9,681 KB55000张训练集
train-labels-idx1-ubyte.gz29 KB训练集图片对应的标签
t10k-images-idx3-ubyte.gz1,611 KB10000张测试集
t10k-labels-idx1-ubyte.gz5 KB测试集图片对应的标签

训练集中前20个样本图形如下图所示:
在这里插入图片描述

数据集的导入: (下面模块中均包含有该数据集)

在这里插入图片描述

四、环境准备

以下是我的运行环境(供参考)

  1. Python 3.9.13 (其它与tensorflow对应版本均可)
  2. PyCharm 2022.3 (Professional Edition)
  3. jupyter notebook (备选)
  4. tensorflow-gpu==2.10.0 (使用GPU进行加速,需单独安装该版本,详见下面文档)
  5. cuDNN==8.1 (tensorflow-gpu显卡依赖)
  6. CUDA==11.2 (tensorflow-gpu显卡依赖)
  7. numpy==1.23.3 (python科学计算库)

官方TensorFlow安装文档 (安装必看)

五、实验要求

1.使用TensorFlow的Sequential实现前馈神经网络,并完成手写数字识别任务。

包括数据集的读取,模型的建立,模型的训练,模型的测试。

2.使用TensorFlow的基础功能实现前馈神经网络,并完成手写数字识别任务。

包括数据集的读取,模型的建立,计算损失、准确性等功能的实现,使用梯度带完成模型的训练,模型的测试。

3.使用sk-learn实现支持向量机,并完成手写数字识别任务。

包括数据集的读取,模型的建立,模型的训练,模型的测试

4.手写实现前馈神经网络(仅允许使用numpy,需要手写反向传播算法求解过程)

  • 其重点是手写反向传播算法,可以在对预测结果取log时,记下取log前的结果,便于求解交叉熵损失函数的导数。在求解softmax函数的导数时,也可以将求导结果中的对角阵与外积分别根据链式法则乘以之前的结果(交叉熵损失函数的导数)。手写完后,需要与TensorFlow的反向传播算法对比一下。
  • 参考 GitHub - nndl/nndl-exercise-ans: Solutions for nndl/exercise

2.手写支持向量机(包括支持向量机的优化算法——SMO算法)

  • 支持向量机不能用常规算法进行优化,但可以使用特有的优化算法:SMO算法。
  • 参考 知乎专栏:支持向量机(SVM)——SMO算法

具体的分析及说明见下面代码注释.

六、Python代码

tutorial_minst_fnn-keras.py:使用TensorFlow的Sequential实现的前馈神经网络

# -*- coding: utf-8 -*-
# @Author : Xenon
# @Date : 2022/12/3 23:55 
# @IDE : PyCharm(2022.2.3) Python3.9.13
"""使用TensorFlow的Sequential实现前馈神经网络"""
import os
import tensorflow as tf
from tensorflow import keras
from keras.datasets import mnist
from tensorflow.python.keras import layers
from keras.api.keras import optimizers# from tensorflow.keras import layers, optimizers, datasets 该导入方式虽然会报错但也能正常运行
# from keras.api.keras import layers 也可选择该方式导入layers# 设置log信息等级 INFO(通知0)<WARNING(警告1)<ERROR(错误2)<FATAL(致命的3)
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '1'  # or any {'0', '1', '2','3'}def mnist_dataset():"""读取TensorFlow自带的mnist手写字体数据集。:return:训练集ds, 测试集test_ds(使用TensorFlow的dataset形式)"""# 从训练集提取20000个数据(共60000个)(x, y), (x_test, y_test) = mnist.load_data()  # 加载MNIST数据集。# 创建一个数据集,其元素是给定张量的切片。切片2维张量生成1维张量元素。ds = tf.data.Dataset.from_tensor_slices((x, y))# 将数据打乱顺序并分成200个batch,每个batch有100个样本。ds = ds.map(prepare_mnist_features_and_labels)  # 将map_func映射到此数据集的元素ds = ds.take(20000).shuffle(20000).batch(100)  # 装载20000数据集打乱后分为100批# 从测试集提取全部20000个数据,prepare_mnist_features_and_labels,打乱顺序,设置为1个batchtest_ds = tf.data.Dataset.from_tensor_slices((x_test, y_test))test_ds = test_ds.map(prepare_mnist_features_and_labels)test_ds = test_ds.take(20000).shuffle(20000).batch(20000)return ds, test_dsdef prepare_mnist_features_and_labels(x, y):"""将x转化成TensorFlow的32位浮点数(tf.float32),并除以255.0,将y转化成TensorFlow的64位整数(tf.int64):param x: 原始张量x:param y: 原始张量y:return: x,y (dtype新类型)"""# 将张量强制转换为dtype新类型x = tf.cast(x, tf.float32) / 255.0y = tf.cast(y, tf.int64)return x, yif __name__ == '__main__':# 创建顺序模型实例。形参:layers–要添加到模型中的图层的可选列表。name–模型的可选名称model = keras.Sequential([# 将输入值转换成一维向量,注意:该层是对数据的一种处理,在算法上并不认为是一层。layers.Reshape(target_shape=(28 * 28,)),# 第一隐含层,全连接层,100个神经元,激活函数为relu函数。layers.Dense(100, activation='relu'),# 第二隐含层,形式同上layers.Dense(100, activation='relu'),# 输出层,10个神经元,无激活函数layers.Dense(10)# Dense实现了以下操作:输出=激活(点(输入,内核)+偏置),其中激活是作为激活参数传递的元素激活函数,# 内核是由层创建的权重矩阵,偏置是由层生成的偏置向量(仅当use_bias为True时适用)。这些都是“密集”的属性。])# 实现Adam算法的优化器。Adam优化是一种基于一阶和二阶矩自适应估计的随机梯度下降方法optimizer = optimizers.Adam(0.0001)  # 学习率设置为0.0001# 配置用于训练的模型model.compile(optimizer=optimizer,  # 优化器实例loss='sparse_categorical_crossentropy',  # 指定损失函数为交叉熵损失函数metrics=['accuracy'],  # 指定模型评估度量指标为accuracy(精确度))train_ds, test_ds = mnist_dataset()  # 得到训练集和测试集# Trains the model for a fixed number of epochs (iterations on a dataset).model.fit(train_ds, epochs=5)  # 指定模型迭代次数为5次x = model.evaluate(test_ds)  # 返回测试模式下模型的损失值和度量值print("loss value: ", x[0])print("metrics: ", x[1])

tutorial_minst_fnn-tf2.0.py:使用TensorFlow的基础功能实现前馈神经网络

# -*- coding: utf-8 -*-
# @Author : Xenon
# @Date : 2022/12/3 23:57 
# @IDE : PyCharm(2022.2.3) Python3.9.13
"""使用TensorFlow的基础功能实现前馈神经网络"""
import os
import tensorflow as tf
from keras.datasets import mnist
from keras.api.keras import optimizers# from tensorflow.keras import layers, optimizers, datasets# 设置log信息等级 INFO(通知0)<WARNING(警告1)<ERROR(错误2)<FATAL(致命的3)
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'def mnist_dataset():"""读取TensorFlow自带的mnist手写字体数据集。:return:训练集ds, 测试集test_ds(使用TensorFlow的dataset形式)"""# 从训练集提取20000个数据(共60000个)(x, y), (x_test, y_test) = mnist.load_data()  # 加载MNIST数据集。# 创建一个数据集,其元素是给定张量的切片。切片2维张量生成1维张量元素。ds = tf.data.Dataset.from_tensor_slices((x, y))# 将数据打乱顺序并分成200个batch,每个batch有100个样本。ds = ds.map(prepare_mnist_features_and_labels)  # 将map_func映射到此数据集的元素ds = ds.take(20000).shuffle(20000).batch(100)  # 装载20000个数据集打乱后分为100批# 从测试集提取全部20000个数据,prepare_mnist_features_and_labels,打乱顺序,设置为1个batchtest_ds = tf.data.Dataset.from_tensor_slices((x_test, y_test))test_ds = test_ds.map(prepare_mnist_features_and_labels)test_ds = test_ds.take(20000).shuffle(20000).batch(20000)return ds, test_dsdef prepare_mnist_features_and_labels(x, y):"""将x转化成TensorFlow的32位浮点数(tf.float32),并除以255.0,将y转化成TensorFlow的64位整数(tf.int64):param x: 原始张量x:param y: 原始张量y:return: x,y (dtype新类型)"""# 将张量强制转换为dtype新类型x = tf.cast(x, tf.float32) / 255.0y = tf.cast(y, tf.int64)return x, yclass MyModel:"""自定义模型类"""def __init__(self):# tf.Variable类型数据,形状为[28*28, 100],数据类型为tf.float32,初始值为-0.1到0.1的随机数,初始值形状与W1本身形状相同。self.W1 = tf.Variable(shape=[28 * 28, 100], dtype=tf.float32,initial_value=tf.random.uniform(shape=[28 * 28, 100],minval=-0.1, maxval=0.1))# tf.Variable类型数据,形状为[100],数据类型为tf.float32,初始值为0,初始值形状与b1本身形状相同。self.b1 = tf.Variable(shape=[100], dtype=tf.float32, initial_value=tf.zeros(100))# 以上属性说明,第一隐含层有100个神经元,上一层(第0层,输入层)有28*28=784个神经元# tf.Variable类型数据,形状为[100, 10],数据类型为tf.float32,初始值为-0.1到0.1的随机数,初始值形状与W2本身形状相同。self.W2 = tf.Variable(shape=[100, 10], dtype=tf.float32,initial_value=tf.random.uniform(shape=[100, 10],minval=-0.1, maxval=0.1))# tf.Variable类型数据,形状为[10],数据类型为tf.float32,初始值为0,初始值形状与b2本身形状相同。self.b2 = tf.Variable(shape=[10], dtype=tf.float32, initial_value=tf.zeros(10))# 以上属性说明,输出层有10个神经元,上一层(第一隐含层)有100个神经元# 由self.W1, self.W2, self.b1, self.b2构成的列表self.trainable_variables = [self.W1, self.W2, self.b1, self.b2]def __call__(self, x):"""将输入的属性集中每一个二维样本转化为一维注意,输入的是所有二维样本,因此共有三维,转化成相同数量的一维样本,因此转化之后共有二维)。:param x: 输入的属性集:return: 相同数量的一维样本"""flat_x = tf.reshape(x, shape=[-1, 28 * 28])# 将结果其与W1矩阵相乘,加上偏置b1,然后用tanh激活函数处理。# (注意,此时的输入值相当于转置的X,因此是X乘以W1,而非相反)h1 = tf.tanh(tf.matmul(flat_x, self.W1) + self.b1)# 将结果其与W2矩阵相乘,加上偏置b2,不用激活函数处理。logists = tf.matmul(h1, self.W2) + self.b2return logists@tf.function
def compute_loss(logits, labels):"""计算交叉熵损失函数使用TensorFlow中的交叉熵损失函数,规定样本预测标签为logits形式,需要用softmax函数处理,真实标签未经独热向量处理,需要自动处理。然后返回平均损失。:param logits:Logits形式的预测标签logits:param labels:经独热向量处理的真实标签labels:return:平均损失loss"""return tf.reduce_mean(# 计算逻辑和标签之间的稀疏软最大交叉熵tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits, labels=labels))@tf.function
def compute_accuracy(logits, labels):"""计算准确性鉴于样本的标签是0-9,与数组下标相同,利用这一点进行判断。:param logits: Logits形式的预测标签logits:param labels: 未经独热向量处理的真实标签labels:return: 准确率"""# 对预测标签logits使用tf.argmax函数(注意维度为1),得到预测结果predictionspredictions = tf.argmax(logits, axis=1)# 使用tf.equal函数判断预测标签与真实标签是否相同,再计算准确率。return tf.reduce_mean(tf.cast(tf.equal(predictions, labels), tf.float32))@tf.function
def train_one_step(model, optimizer, x, y):""" 进行训练(一个时间步):param model:模型model:param optimizer:优化器optimizer(用于指定优化方法):param x:属性集x:param y:真实标签集y:return:损失loss, 准确性accuracy"""# 在梯度带中,调用模型的__call__方法with tf.GradientTape() as tape:logists = model(x)loss = compute_loss(logists, y)# 预测样本的标签,并调用compute_loss函数计算损失值。grads = tape.gradient(loss, model.trainable_variables)# 利用梯度带进行一次随机梯度下降法训练。optimizer.apply_gradients(zip(grads, model.trainable_variables))# 调用compute_accuracy函数计算准确性。accuracy = compute_accuracy(logists, y)return loss, accuracy@tf.function
def _test_step(model, x, y):"""执行预测调用模型的__call__方法,预测样本的标签。:param model:模型model:param x:属性集x:param y:真实标签集y:return:损失loss, 准确性accuracy"""logists = model(x)# 调用compute_loss函数计算损失值。loss = compute_loss(logists, y)# 调用compute_accuracy函数计算准确性。accuracy = compute_accuracy(logists, y)return loss, accuracydef train(epoch, model, optimizer, ds):"""进行训练(所有时间步):param epoch:轮数epoch:param model:模型model:param optimizer:优化器optimizer:param ds:数据集ds:return:损失loss, 准确性accuracy"""loss = 0.0accuracy = 0.0# 遍历数据集(TensorFlow的dataset形式)中的样本,调用train_one_step函数进行训练,for step, (x, y) in enumerate(ds):loss, accuracy = train_one_step(model, optimizer, x, y)# 每次取出一个batch,在最后一个batch结束后,输出此刻的epoch, loss, accuracy。print('epoch', epoch, ': loss', loss.numpy(), '; accuracy', accuracy.numpy())return loss, accuracydef my_test(model, ds):"""进行测试:param model:模型model:param ds:数据集ds:return:损失loss, 准确性accuracy"""loss = 0.0accuracy = 0.0# 遍历数据集(TensorFlow的dataset形式)中的样本,调用test_step函数进行测试,每次取出一个batch,for step, (x, y) in enumerate(ds):loss, accuracy = _test_step(model, x, y)# 在最后一个batch结束后,输出此刻的loss, accuracy。(注:本实验中,测试集只有一个batch)print('<test loss>', loss.numpy(), '; <test accuracy>', accuracy.numpy())return loss, accuracyif __name__ == '__main__':print("start")model = MyModel()  # 实列化自定义模型optimizer = optimizers.Adam()  # 实现Adam算法的优化器# 调用函数mnist_dataset(),获取数据集train_ds, test_ds。train_ds, test_ds = mnist_dataset()# 在5轮中,利用train函数进行训练。for epoch in range(5):loss, accuracy = train(epoch, model, optimizer, train_ds)# 利用test函数进行测试。loss, accuracy = my_test(model, test_ds)print("real损失loss: %f ; real准确性accuracy: %f" % (loss.numpy(), accuracy.numpy()))

SVM_sklearn.py:使用sk-learn实现支持向量机

# -*- coding: utf-8 -*-
# @Author : Xenon
# @Date : 2022/12/3 23:57 
# @IDE : PyCharm(2022.2.3) Python3.9.13
"""使用sk-learn实现支持向量机,并完成手写数字识别任务。"""import numpy as np
# import operator
from os import listdir
from sklearn.svm import SVCdef img2vector(filename):"""将一张图片转化为一维向量:param filename:文件名filename:return:转换后的向量returnVect"""# 创建全0的numpy数组,形状为(1,1024)returnVect = np.zeros((1, 1024))fr = open(filename)  # 读取文件# 将第i行j列的像素赋值给numpy数组的32*i+j个元素,将所有像素进行赋值。for i in range(32):lineStr = fr.readline()for j in range(32):returnVect[0, 32 * i + j] = int(lineStr[j])return returnVectdef run():hwLabels = []  # 存储测试集的LabelstrainingDigits_path = "E:/wynuJunior/模式识别/6前馈神经网络与支持向量机/新建文件夹/trainingDigits"testDigits_path = "E:/wynuJunior/模式识别/6前馈神经网络与支持向量机/新建文件夹/testDigits"trainingFileList = listdir(trainingDigits_path)  # 使用listdir返回trainingDigits目录下的文件名if '.ipynb_checkpoints' in trainingFileList:trainingFileList.remove('.ipynb_checkpoints')m = len(trainingFileList)  # 返回文件夹下文件的个数# 初始化训练的trainingMat矩阵为(m, 1024)形状的全零numpy数组,trainingMat = np.zeros((m, 1024))# 依次读取trainingDigits目录下的文件for i in range(m):fileNameStr = trainingFileList[i]classNumber = int(fileNameStr.split('_')[0])  # 将文件名中下划线“_”前面的字符作为类别hwLabels.append(classNumber)# 使用img2vector函数读取属性并转化为一维向量.分别存储在hwLabels与trainingMat矩阵中trainingMat[i, :] = img2vector(trainingDigits_path + "/" + fileNameStr)# 将SVC模型实例化,松弛向量超参数C为200,核函数为rbfclf = SVC(C=200, kernel='rbf')# 调用fit方法,输入trainingMat与hwLabelsclf.fit(trainingMat, hwLabels)testFileList = listdir(testDigits_path)if '.ipynb_checkpoints' in trainingFileList:trainingFileList.remove('.ipynb_checkpoints')errorCount = 0.0mTest = len(testFileList)# 使用相同的方法读取测试数据,测试数据存储在文件夹testDigits中,每读取一个数据,# 调用SVC模型的predict方法进行预测,输出分类返回结果,真实结果,并统计错误次数,最终输出错误率。for i in range(mTest):fileNameStr = testFileList[i]classNumber = int(fileNameStr.split('_')[0])vectorUnderTest = img2vector(testDigits_path + "/" + fileNameStr)classifierResult = clf.predict(vectorUnderTest)print("分类返回结果为%d\t真实结果为%d" % (classifierResult, classNumber))if classifierResult != classNumber:errorCount += 1.0print("总共错了%d个数据\n错误率为%f%%" % (errorCount, errorCount / mTest * 100))if __name__ == '__main__':run()

tutorial_minst_fnn-numpy.py:手写实现前馈神经网络(仅使用numpy,包括手写反向传播算法求解过程)

# -*- coding: utf-8 -*-
# @Author : Xenon
# @Date : 2022/12/3 23:58 
# @IDE : PyCharm(2022.2.3) Python3.9.13
"""手写实现前馈神经网络(仅允许使用numpy,需要手写反向传播算法求解过程)
神经网络与深度学习(邱锡鹏)编程练习4 FNN 简单神经网络 Jupyter导出版 numpy """
import os
import numpy as np
from keras.datasets import mnist
import tensorflow as tf# 设置log信息等级 INFO(通知0)<WARNING(警告1)<ERROR(错误2)<FATAL(致命的3)
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'# =============== 准备数据 ===============
def mnist_dataset():"""读取mnist手写字体数据集。:return:训练集(x, y), 测试集(x_test, y_test)"""(x, y), (x_test, y_test) = mnist.load_data()x = x / 255.0x_test = x_test / 255.0return (x, y), (x_test, y_test)# ===============Demo numpy based auto differentiation===============
class Matmul:def __init__(self):self.mem = {}def forward(self, x, W):"""前向传播"""h = np.matmul(x, W)self.mem = {'x': x, 'W': W}return hdef backward(self, grad_y):"""反向传播x: shape(N, d)w: shape(d, d')grad_y: shape(N, d')"""x = self.mem['x']W = self.mem['W']grad_x = np.matmul(grad_y, W.T)  # shape(N, b)grad_W = np.matmul(x.T, grad_y)return grad_x, grad_Wclass Relu:def __init__(self):self.mem = {}def forward(self, x):"""前向传播"""self.mem['x'] = xreturn np.where(x > 0, x, np.zeros_like(x))def backward(self, grad_y):"""反向传播grad_y: same shape as x"""x = self.mem['x']return (x > 0).astype(np.float32) * grad_yclass Softmax:"""softmax over last dimention"""def __init__(self):self.epsilon = 1e-12self.mem = {}def forward(self, x):"""前向传播x: shape(N, c)"""x_exp = np.exp(x)partition = np.sum(x_exp, axis=1, keepdims=True)out = x_exp / (partition + self.epsilon)self.mem['out'] = outself.mem['x_exp'] = x_expreturn outdef backward(self, grad_y):"""反向传播grad_y: same shape as x"""s = self.mem['out']sisj = np.matmul(np.expand_dims(s, axis=2), np.expand_dims(s, axis=1))  # (N, c, c)g_y_exp = np.expand_dims(grad_y, axis=1)tmp = np.matmul(g_y_exp, sisj)  # (N, 1, c)tmp = np.squeeze(tmp, axis=1)tmp = -tmp + grad_y * sreturn tmpclass Log:"""softmax over last dimention"""def __init__(self):self.epsilon = 1e-12self.mem = {}def forward(self, x):"""前向传播x: shape(N, c)"""out = np.log(x + self.epsilon)self.mem['x'] = xreturn outdef backward(self, grad_y):"""反向传播grad_y: same shape as x"""x = self.mem['x']return 1. / (x + 1e-12) * grad_y# ===============Gradient check===============
def Gradient_check():x = np.random.normal(size=[5, 6])W1 = np.random.normal(size=[6, 5])W2 = np.random.normal(size=[5, 6])label = np.zeros_like(x)label[0, 1] = 1.label[1, 0] = 1label[2, 3] = 1label[3, 5] = 1label[4, 0] = 1mul_h1 = Matmul()mul_h2 = Matmul()relu = Relu()softmax = Softmax()log = Log()h1 = mul_h1.forward(x, W1)  # shape(5, 4)h1_relu = relu.forward(h1)h2 = mul_h2.forward(h1_relu, W2)h2_soft = softmax.forward(h2)h2_log = log.forward(h2_soft)h2_log_grad = log.backward(label)h2_soft_grad = softmax.backward(h2_log_grad)h2_grad, W2_grad = mul_h2.backward(h2_soft_grad)h1_relu_grad = relu.backward(h2_grad)h1_grad, W1_grad = mul_h1.backward(h1_relu_grad)print(h2_log_grad)print('--' * 20)# print(W2_grad)with tf.GradientTape() as tape:x, W1, W2, label = tf.constant(x), tf.constant(W1), tf.constant(W2), tf.constant(label)tape.watch(W1)tape.watch(W2)h1 = tf.matmul(x, W1)h1_relu = tf.nn.relu(h1)h2 = tf.matmul(h1_relu, W2)prob = tf.nn.softmax(h2)log_prob = tf.math.log(prob)loss = tf.reduce_sum(label * log_prob)grads = tape.gradient(loss, [prob])print(grads[0].numpy())# ===============建立模型===============
class MyModel:def __init__(self):self.W1 = np.random.normal(size=[28 * 28 + 1, 100])self.W2 = np.random.normal(size=[100, 10])self.mul_h1 = Matmul()self.mul_h2 = Matmul()self.relu = Relu()self.softmax = Softmax()self.log = Log()def forward(self, x):x = x.reshape(-1, 28 * 28)bias = np.ones(shape=[x.shape[0], 1])x = np.concatenate([x, bias], axis=1)self.h1 = self.mul_h1.forward(x, self.W1)  # shape(5, 4)self.h1_relu = self.relu.forward(self.h1)self.h2 = self.mul_h2.forward(self.h1_relu, self.W2)self.h2_soft = self.softmax.forward(self.h2)self.h2_log = self.log.forward(self.h2_soft)def backward(self, label):self.h2_log_grad = self.log.backward(-label)self.h2_soft_grad = self.softmax.backward(self.h2_log_grad)self.h2_grad, self.W2_grad = self.mul_h2.backward(self.h2_soft_grad)self.h1_relu_grad = self.relu.backward(self.h2_grad)self.h1_grad, self.W1_grad = self.mul_h1.backward(self.h1_relu_grad)# ===============计算 loss===============
def compute_loss(log_prob, labels):"""计算交叉熵损失函数使用TensorFlow中的交叉熵损失函数,规定样本预测标签为logits形式,需要用softmax函数处理,真实标签未经独热向量处理,需要自动处理。然后返回平均损失。:param log_prob:Logits形式的预测标签logits:param labels:经独热向量处理的真实标签labels:return:平均损失loss"""return np.mean(np.sum(-log_prob * labels, axis=1))def compute_accuracy(log_prob, labels):"""计算精确度鉴于样本的标签是0-9,与数组下标相同,利用这一点进行判断。:param log_prob: Logits形式的预测标签:param labels: 未经独热向量处理的真实标签labels:return: 准确率"""predictions = np.argmax(log_prob, axis=1)truth = np.argmax(labels, axis=1)return np.mean(predictions == truth)def train_one_step(model, x, y):"""进行训练(一个时间步)"""model.forward(x)model.backward(y)model.W1 -= 1e-5 * model.W1_gradmodel.W2 -= 1e-5 * model.W2_gradloss = compute_loss(model.h2_log, y)accuracy = compute_accuracy(model.h2_log, y)return loss, accuracydef _test(model, x, y):"""执行预测"""model.forward(x)loss = compute_loss(model.h2_log, y)accuracy = compute_accuracy(model.h2_log, y)return loss, accuracy# ===============实际训练===============
def train():model = MyModel()train_data, test_data = mnist_dataset()train_label = np.zeros(shape=[train_data[0].shape[0], 10])test_label = np.zeros(shape=[test_data[0].shape[0], 10])train_label[np.arange(train_data[0].shape[0]), np.array(train_data[1])] = 1.test_label[np.arange(test_data[0].shape[0]), np.array(test_data[1])] = 1.for epoch in range(50):loss, accuracy = train_one_step(model, train_data[0], train_label)print('epoch', epoch, ': loss', loss, '; accuracy', accuracy)loss, accuracy = _test(model, test_data[0], test_label)print('test loss', loss, '; accuracy', accuracy)if __name__ == '__main__':print(">>>>>>>>>>Final Gradient Check:")Gradient_check()print("\n>>>>>>>>>>>>>实际训练:")train()

SVM_manual.py:手写支持向量机(包括支持向量机的优化算法——SMO算法)

# -*- coding: utf-8 -*-
# @Author : Xenon
# @Date : 2022/12/3 23:59 
# @IDE : PyCharm(2022.2.3) Python3.9.13
"""手写支持向量机(包括支持向量机的优化算法——SMO算法)"""
import numpy as npnp.random.seed(1)  # 设置初始随机数种子class SVC:def __init__(self, max_iter=100, C=1, kernel='rbf', sigma=1):self.b = 0.self.alpha = Noneself.max_iter = max_iterself.C = Cself.kernel = kernelself.K = Noneself.X = Noneself.y = Noneif kernel == 'rbf':self.sigma = sigmadef kernel_func(self, kernel, x1, x2):if kernel == 'linear':return x1.dot(x2.T)elif kernel == 'rbf':return np.exp(-(np.sum((x1 - x2) ** 2)) / (2 * self.sigma * self.sigma))def computeK(self, X, kernel):m = X.shape[0]K = np.zeros((m, m))for i in range(m):for j in range(m):if i <= j:K[i, j] = self.kernel_func(kernel, X[i], X[j])else:K[i, j] = K[j, i]return Kdef compute_u(self, X, y):u = np.zeros((X.shape[0],))for j in range(X.shape[0]):u[j] = np.sum(y * self.alpha * self.K[:, j]) + self.breturn udef checkKKT(self, u, y, i):if self.alpha[i] < self.C and y[i] * u[i] <= 1:return Falseif self.alpha[i] > 0 and y[i] * u[i] >= 1:return Falseif (self.alpha[i] == 0 or self.alpha[i] == self.C) and y[i] * u[i] == 1:return Falsereturn Truedef fit(self, X, y):self.X = Xself.y = yself.K = self.computeK(X, self.kernel)self.alpha = np.random.random((X.shape[0],))self.omiga = np.zeros((X.shape[0],))for _ in range(self.max_iter):u = self.compute_u(X, y)finish = Truefor i in range(X.shape[0]):if not self.checkKKT(u, y, i):finish = Falsey_indices = np.delete(np.arange(X.shape[0]), i)j = y_indices[int(np.random.random() * len(y_indices))]E_i = np.sum(self.alpha * y * self.K[:, i]) + self.b - y[i]E_j = np.sum(self.alpha * y * self.K[:, j]) + self.b - y[j]if y[i] != y[j]:L = max(0, self.alpha[j] - self.alpha[i])H = min(self.C, self.C + self.alpha[j] - self.alpha[i])else:L = max(0, self.alpha[j] + self.alpha[i] - self.C)H = min(self.C, self.alpha[j] + self.alpha[i])eta = self.K[i, i] + self.K[j, j] - 2 * self.K[i, j]alpha2_new_unc = self.alpha[j] + y[j] * (E_i - E_j) / etaalpha2_old = self.alpha[j]alpha1_old = self.alpha[i]if alpha2_new_unc > H:self.alpha[j] = Helif alpha2_new_unc < L:self.alpha[j] = Lelse:self.alpha[j] = alpha2_new_uncself.alpha[i] = alpha1_old + y[i] * y[j] * (alpha2_old - self.alpha[j])b1_new = -E_i - y[i] * self.K[i, i] * (self.alpha[i] - alpha1_old) - y[j] * self.K[j, i] * (self.alpha[j] - alpha2_old) + self.bb2_new = -E_j - y[i] * self.K[i, j] * (self.alpha[i] - alpha1_old) - y[j] * self.K[j, j] * (self.alpha[j] - alpha2_old) + self.bif 0 < self.alpha[i] < self.C:self.b = b1_newelif 0 < self.alpha[j] < self.C:self.b = b2_newelse:self.b = (b1_new + b2_new) / 2if finish:breakdef predict(self, X):y_preds = []for i in range(X.shape[0]):K = np.zeros((len(self.y),))support_indices = np.where(self.alpha > 0)[0]for j in support_indices:K[j] = self.kernel_func(self.kernel, self.X[j], X[i])y_pred = np.sum(self.y[support_indices] * self.alpha[support_indices] * K[support_indices].T)y_pred += self.by_preds.append(y_pred)return np.array(y_preds)def rbf_test():"""# 测试rbf核"""X = np.array([[1, 0], [-1, 0], [0, -1], [0, 1], [2, np.sqrt(5)],[2, -np.sqrt(5)], [-2, np.sqrt(5)], [-2, -np.sqrt(5)],[300, 400]])y = np.array([-1, -1, -1, -1, 1, 1, 1, 1, 1])svc = SVC(max_iter=100, kernel='rbf', C=1)if __name__ == '__main__':# 测试 线性核X = np.array([[2, -1], [3, -2], [1, 0], [0, 1], [-2, 1], [-1.3, 0.3], [-0.2, -0.8], [2.3, -3.3], [-2, -4], [7, 8]])y = np.array([1, 1, 1, 1, -1, -1, -1, -1, -1, 1])svc = SVC(max_iter=100, kernel='linear', C=1)# rbf_test() # 测试rbf核svc.fit(X, y)print('alpha:', svc.alpha)print('b:', svc.b)pred_y = svc.predict(np.array([[1, 0], [-0.2, -0.1], [0, 1]]))print('pred_y1:', pred_y)pred_y = np.sign(pred_y)print('pred_y:', pred_y)

七、实验结果分析

tutorial_minst_fnn-keras.py:使用TensorFlow的Sequential实现的前馈神经网络

在这里插入图片描述

tutorial_minst_fnn-tf2.0.py:使用TensorFlow的基础功能实现前馈神经网络

在这里插入图片描述

SVM_sklearn.py:使用sk-learn实现的支持向量机

在这里插入图片描述

tutorial_minst_fnn-numpy.py:手写实现前馈神经网络

>>>>>>>>>>Final Gradient Check:
[[  0.          13.56517147   0.           0.           0.0.        ][  9.13109205   0.           0.           0.           0.0.        ][  0.           0.           0.          28.76783616   0.0.        ][  0.           0.           0.           0.           0.2.08812302][223.30349106   0.           0.           0.           0.0.        ]]
----------------------------------------
[[  0.          13.56517147   0.           0.           0.0.        ][  9.13109205   0.           0.           0.           0.0.        ][  0.           0.           0.          28.76783616   0.0.        ][  0.           0.           0.           0.           0.2.08812302][223.30349111   0.           0.           0.           0.0.        ]]
>>>>>>>>>>>>>实际训练:
epoch 0 : loss 22.744282639414152 ; accuracy 0.14281666666666668
epoch 1 : loss 21.758409494243114 ; accuracy 0.19443333333333335
epoch 2 : loss 21.055453298219938 ; accuracy 0.21456666666666666
epoch 3 : loss 19.97412670942362 ; accuracy 0.2425
epoch 4 : loss 19.331889706730408 ; accuracy 0.27365
epoch 5 : loss 18.67261661508262 ; accuracy 0.28918333333333335
epoch 6 : loss 18.05297102157659 ; accuracy 0.3132666666666667
epoch 7 : loss 17.391424059042368 ; accuracy 0.3335666666666667
epoch 8 : loss 16.92636561898056 ; accuracy 0.3537
epoch 9 : loss 16.468125340459746 ; accuracy 0.36415
epoch 10 : loss 16.029440126389247 ; accuracy 0.38426666666666665
epoch 11 : loss 15.124473109925919 ; accuracy 0.4094
epoch 12 : loss 14.933236383252314 ; accuracy 0.42401666666666665
epoch 13 : loss 14.077481388808991 ; accuracy 0.4544
epoch 14 : loss 13.822439579397273 ; accuracy 0.46923333333333334
epoch 15 : loss 13.569737829512812 ; accuracy 0.4776666666666667
epoch 16 : loss 13.408817890037813 ; accuracy 0.48535
epoch 17 : loss 13.251820335335175 ; accuracy 0.49325
epoch 18 : loss 13.131440207863612 ; accuracy 0.4978666666666667
epoch 19 : loss 13.030534873523466 ; accuracy 0.50235
epoch 20 : loss 12.941951598415892 ; accuracy 0.50645
epoch 21 : loss 12.864857315106821 ; accuracy 0.5098166666666667
epoch 22 : loss 12.795055337736255 ; accuracy 0.5131
epoch 23 : loss 12.731265095920785 ; accuracy 0.5157333333333334
epoch 24 : loss 12.672742610871332 ; accuracy 0.5183166666666666
epoch 25 : loss 12.619165846144682 ; accuracy 0.521
epoch 26 : loss 12.570194346481664 ; accuracy 0.5236333333333333
epoch 27 : loss 12.525412347113768 ; accuracy 0.5256166666666666
epoch 28 : loss 12.484171010564536 ; accuracy 0.5274666666666666
epoch 29 : loss 12.445748592079973 ; accuracy 0.5291166666666667
epoch 30 : loss 12.409322682637926 ; accuracy 0.5306666666666666
epoch 31 : loss 12.375371239003229 ; accuracy 0.5323
epoch 32 : loss 12.343667769125867 ; accuracy 0.5334666666666666
epoch 33 : loss 12.313774902029765 ; accuracy 0.5348
epoch 34 : loss 12.285461088940856 ; accuracy 0.5360833333333334
epoch 35 : loss 12.258628543611174 ; accuracy 0.5373833333333333
epoch 36 : loss 12.233472765057796 ; accuracy 0.53875
epoch 37 : loss 12.20993121146134 ; accuracy 0.5399666666666667
epoch 38 : loss 12.187759138875334 ; accuracy 0.5408833333333334
epoch 39 : loss 12.166864181880165 ; accuracy 0.5418
epoch 40 : loss 12.147133028128476 ; accuracy 0.5427833333333333
epoch 41 : loss 12.128473068549651 ; accuracy 0.5436333333333333
epoch 42 : loss 12.11088791201951 ; accuracy 0.54475
epoch 43 : loss 12.094389768803017 ; accuracy 0.5456666666666666
epoch 44 : loss 12.078837652166147 ; accuracy 0.54635
epoch 45 : loss 12.063933847899557 ; accuracy 0.5471333333333334
epoch 46 : loss 12.04946994696933 ; accuracy 0.5477
epoch 47 : loss 12.035382923777563 ; accuracy 0.5485166666666667
epoch 48 : loss 12.021645774882836 ; accuracy 0.54925
epoch 49 : loss 12.00810636704182 ; accuracy 0.5498666666666666
test loss 12.11529551663803 ; accuracy 0.5449

SVM_manual.py:手写实现支持向量机

在这里插入图片描述

相关文章:

常见的排序算法——归并排序(三)

本文记述了归并排序的 3 项改进和一份参考实现代码,并在说明了算法的性能后用随机数据进行了验证。 ◆ 思想 本文实现了《算法(第4版)》书中提到的 3 项改进,对小规模子数组使用插入排序。减少在小规模数组中的递归调用能改进整个算法。 测试数组是否已经有序。任意有序的子…...

3.18总结

又到了周一,还是上了几节课程,想吃点水果,去了趟义庄购物中心,报名了四六级考试...

CTF中RSA相关题型总结(持续更新)

e很小时: import gmpy2 from functools import reduce from Crypto.Util.number import long_to_bytes def CRT(items):N = reduce(lambda x, y: x * y, (i[1] for i in items))result = 0for a, n in items:m = N // nd, r, s = gmpy2.gcdext(n, m)if d != 1:raise Exception…...

shell条件语句

一、测试 文件测试testtest的语法 test 条件表达式 [ 条件表达式 ] test 选项 文件 -d :判断是否是目录(Directory) -f :判断是否是普通文件(File) -b :判断是否是块设备(block) -c :判断是否是字符设备 -e :判断是否存在 (Exist) -a :判断是否存在 -r :判断…...

Excel中实现md5加密

1.注意事项 (1)在Microsoft Excel上操作 (2)使用完&#xff0c;建议修改的配置全部还原&#xff0c;防止有风险。 2.准备MD5宏插件 MD5加密宏插件放置到F盘下&#xff08;直接F盘下&#xff0c;不用放到具体某一个文件夹下&#xff09; 提示&#xff1a;文件在文章顶部&…...

js前端获取农历日期

对于公历来说&#xff0c;直接 new 一个 Date 就能获取到&#xff0c;而对于农历来讲可就很难了&#xff0c;因为农历需要有许多复杂计算&#xff0c;虽然一般用的甚少&#xff0c;但对于某些场景来说还是会需要的&#xff0c;那么怎样获取农历日期呢&#xff1f; 这里推荐一个…...

前馈神经网络与支持向量机实战 --- 手写数字识别

前馈神经网络与支持向量机实战 — 手写数字识别 文章目录前馈神经网络与支持向量机实战 --- 手写数字识别一、前馈神经网络介绍二、支持向量机介绍三、数据集说明四、环境准备五、实验要求六、Python代码tutorial_minst_fnn-keras.py&#xff1a;使用TensorFlow的Sequential实现…...

idea导入eclipse项目的时候,Java图标变成黄色小J了,怎么解决?

凯哥今天导入一个15年时候写的小项目&#xff0c;当时使用的是eclipse写的。最近好几年都在使用idea&#xff0c;习惯了idea的&#xff0c;在用eclipse&#xff0c;不习惯&#xff0c;不顺手&#xff0c;就导入到idea中。发现&#xff0c;Java文件的图标变成了黄色的J。如下图&…...

Redis配置与优化

1 关系数据库与非关系型数据库概述 1.1 关系型数据库 一个结构化的数据库&#xff0c;创建在关系模型&#xff08;二维表格模型&#xff09;基础上 一般面向于记录 SQL 语句&#xff08;标准数据查询语言&#xff09;就是一种基于关系型数据库的语言 用于执行对关系型数据库中…...

管理团队相关的梳理

管理团队是跟踪团队成员工作表现,提供反馈,解决问题并管理团队变更,以优化项目绩效的过程。本过程的主要作用是,影响团队行为、管理冲突以及解决问题等方式,实现团队管理。 输入 1.项目管理计划 --------资源管理计划 2. 项目文件 --------问题日志、经验教训登记册、项…...

HTML5期末大作业【红色的电影售票平台网站】web前端 html+css+javascript网页设计实例 企业网站制作

HTML实例网页代码, 本实例适合于初学HTML的同学。该实例里面有设置了css的样式设置&#xff0c;有div的样式格局&#xff0c;这个实例比较全面&#xff0c;有助于同学的学习,本文将介绍如何通过从头开始设计个人网站并将其转换为代码的过程来实践设计。 文章目录一、网页介绍一…...

【三维目标检测】Part-A2(一)

Part-A2是商汤在CVPR 2020上发布的三维点云目标检测模型&#xff0c;来源于PointRCNN同一作者&#xff0c;论文名称《From Points to Parts 3D Object Detection from Point Cloud with Part-aware and Part-aggregation Network》。从名称可以看出&#xff0c;Part代表的是目标…...

C++输出四舍五入的一些小问题

嗯…今天刚去练了一会简单题 就我大一刚上学做的那种题&#xff0c;嗯&#xff0c;然后我发现我还是得调试&#xff0c;想骂人了&#xff0c;就啥样的题呢, 嗯,就这样的题&#xff0c;虽然我大一可能也过不了这种题&#xff0c;hh 现在题目里面要求一些四舍五入的问题 刚才没整…...

详解设计模式:责任链模式

责任链模式&#xff08;Chain of Responsibility Pattern&#xff09;也被称为职责链模式&#xff0c;是在 GoF 23 种设计模式中定义了的行为型模式。 责任链模式 是将链中的每一个节点看作是一个对象&#xff0c;每个节点处理的请求不同&#xff0c;且内部自动维护一个下一节点…...

Python源码剖析笔记1-整数对象PyIntObject

1、PyIntObject 对象 [intobject.h] typedef struct {PyObject_HEADlong ob_ival; } PyIntObjectPyIntObject是一个不可变&#xff08;immutable&#xff09;对象。Python内部也大量的使用整数对象&#xff0c;我们在自己的代码中也会有大量的创建销毁整型对象的操作&#xff…...

求一个网页设计作业——个人博客(HTML+CSS)

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…...

HTML5期末大作业:基于html+css+javascript+jquery实现藏族文化15页【学生网页设计作业源码】

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…...

2. IMU原理及姿态融合算法详解

文章目录2. IMU原理及姿态融合算法详解一、组合二、 原理a) 陀螺仪b) 加速度计c) 磁力计三、 旋转的表达a) 欧拉角b) 旋转矩阵c) 四元数d) 李群 SO(3)\text{SO}(3)SO(3) 及 李代数 so(3)\text{so}(3)so(3)四、 传感器的噪声及去除a) 陀螺仪b) 加速度计c) 磁力计五、姿态解算原理…...

【能效管理】安科瑞远程预付费系统在江西某沃尔玛收费管理的应用

摘要&#xff1a;文章根据用电远程管控原理&#xff0c;设计了用电预付费远程管理终端及管理系统&#xff0c;该系统以智能远程预付费电表、智能网关以及预付费管理软件实现了商业综合体的用电管理&#xff0c;实现了欠费自动分闸&#xff0c;充值后自动合闸&#xff0c;并辅助…...

HTML+CSS+JS做一个好看的个人网页—web网页设计作业

个人网页设计个人网页&#xff08;htmlcssjs&#xff09;——网页设计作业带背景音乐&#xff08;The way I still Love you&#xff09;、樱花飘落效果、粒子飘落效果页面美观&#xff0c;样式精美涉及&#xff08;htmlcssjs&#xff09;&#xff0c;下载后可以根据自己需求进…...

【MySQL】表的增删改查(一)

你可以了解世间万物&#xff0c;但追根溯源的唯一途径便是亲身尝试。——《心灵捕手》 前言&#xff1a; 大家好&#xff0c;我是拳击哥&#xff0c;今天给大家讲解的是mysql表GRUD操作中的新增数据、查询数据以及表中数据的排序、去重等。因篇幅过长&#xff0c;分为两期来讲解…...

HTML5期末考核大作业、HTML个人主页界面设计源码

&#x1f389;精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…...

计算机毕业设计Java酒店信息管理(源码+系统+mysql数据库+lw文档)

计算机毕业设计Java酒店信息管理(源码系统mysql数据库lw文档) 计算机毕业设计Java酒店信息管理(源码系统mysql数据库lw文档)本源码技术栈&#xff1a; 项目架构&#xff1a;B/S架构 开发语言&#xff1a;Java语言 开发软件&#xff1a;idea eclipse 前端技术&#xff1a;La…...

ARM 汇编编写 LED 灯

一、一步步点亮LED 1. 硬件工作原理及原理图查阅 LED 本身有 2 个接线点&#xff0c;一个是 LED 的正极&#xff0c;一个是 LED 的负极。LED 这个硬件的功能就是点亮或者不亮&#xff0c;物理上想要点亮一颗 LED 只需要给他的正负极上加正电压即可&#xff0c;要熄灭一颗 LED…...

用python编写远程控制程序

1.前言 远程控制是网络安全的一个极为重要的内容&#xff0c;无论是网络安全的维护者还是破坏者都会对此进行研究。维护者的目标是保证远程控制的安全&#xff0c;而破坏者的目标是希望能够凭借各种手段实现对目标设备的远程控制。 本文主要研究三个内容。 1.如何编写一个基于…...

安装docker,docker-compose

安装docker,docker-composeLinux时间不对ARM同步时间X86同步时间centos8更换源安装dockerARM安装dockerX86安装dockerdocker设置阿里镜像源docker 下载拉取报错安装docker-composeARM X86安装docker-composemac安装docker-composeLinux时间不对 ARM同步时间 # 安装chrony yum…...

一文带你深入理解【Java基础】· 泛型

写在前面 Hello大家好&#xff0c; 我是【麟-小白】&#xff0c;一位软件工程专业的学生&#xff0c;喜好计算机知识。希望大家能够一起学习进步呀&#xff01;本人是一名在读大学生&#xff0c;专业水平有限&#xff0c;如发现错误或不足之处&#xff0c;请多多指正&#xff0…...

RabbitMQ学习笔记

目录 尚硅谷mq视频学习笔记 1.1. MQ 的相关概念 1.1.1. 什么是MQ 1.1.2. 为什么要用MQ 1.1.3. MQ 的分类 1.ActiveMQ 2.Kafka 3.RocketMQ 4.RabbitMQ 1.1.4. MQ 的选择 1.Kafka 2.RocketMQ 3.RabbitMQ 1.2. RabbitMQ 1.2.1. RabbitMQ 的概念 1.2.2. 四大核心概念…...

Java安全-CC1

CC1 这里用的是组长的链子和yso好像不太一样&#xff0c;不过大体上都是差不多的。后半条的链子都是一样的&#xff0c;而且这条更短更易理解。yso的CC1过段时间再看一下。 环境 Maven依赖&#xff1a; <dependencies><dependency><groupId>commons-colle…...

【得到日期对象NSDate的各个部分 Objective-C语言】

一、得到日期对象NSDate的各个部分,年月日时分秒 1.例如,我这儿有1个NSDate对象, NSDate *date = [NSDate date]; 这个日期里面是不是有年、有月、有日、有时、有分、有秒 我想单独的拿到这个日期里面的年,该怎么拿 用date.year属性,行吗,不行,因为没有这个属性 用…...

前端面试常考 | CSS垂直居中解决方案

文章目录一. 前言二. flx布局实现三. Grid布局实现四. 绝对定位transform五. 绝对定位负margin五. 绝对定位calc六. 定位加margin一. 前言 前段时间刷到一篇帖子&#xff0c;说面试竟然遇到了CSS的考点&#xff0c;让回答CSS实现垂直居中的方式有哪些?&#xff0c;都2022年了…...

Flink中的UDF的实现

Flink 的 Table API 和 SQL 提供了多种自定义函数的接口&#xff0c;以抽象类的形式定义。当前 UDF 主要有以下几类&#xff1a; 标量函数&#xff08;Scalar Functions&#xff09;&#xff1a;将输入的标量值转换成一个新的标量值&#xff1b;表函数&#xff08;Table Funct…...

Linux教程

Linux 目录结构 /bin&#xff1a;&#xff08;binary&#xff09;存放的是一些二进制文件&#xff0c;但是在Linux中二进制文件是可以被执行的。这个目录中的命令文件是给普通用户使用&#xff08;非超级管理员用户&#xff09;。 /etc&#xff1a;Linux下所有的配置文件都会…...

1.3 Apache Hadoop的重要组成-hadoop-最全最完整的保姆级的java大数据学习资料

文章目录1.3 Apache Hadoop的重要组成1.3 Apache Hadoop的重要组成 HadoopHDFS(分布式文件系统)MapReduce(分布式计算框架)Yarn(资源协调框架)Common模块 Hadoop HDFS&#xff1a;&#xff08;Hadoop Distribute File System &#xff09;一个高可靠、高吞吐量的分布式文件系统…...

【蓝桥杯】第十四届模拟赛第一期及第二期填空汇总

目录 1.A题&#xff08;进制位数&#xff09; 位运算符 第一期 问题描述 解析 第二期 解析 代码 2.B题&#xff08;日期问题&#xff09; 第一期 问题描述 解析 代码实现 执行结果 第二期 问题描述 解析 3.C题&#xff08;数学问题&#xff09; 第一期 问题…...

Go学习之路-环境搭建

默认运行设备系统&#xff1a;MacOS 安装 安装包下载地址&#xff08;下面3个都可以&#xff09;&#xff1a; https://studygolang.com/dl https://golang.google.cn/dl/ https://golang.org/dl/ 我这里选择 pkg包、一键安装、默认的安装路径 /usr/local/go 环境 设置go语言…...

Siamese Neural Network (SNN: 孪生神经网络)

【学习参考】&#xff1a; https://blog.csdn.net/MyArrow/article/details/122539749https://blog.csdn.net/MyArrow/article/details/122539749 Siamese network 孪生神经网络--一个简单神奇的结构 - 知乎 (zhihu.com)https://zhuanlan.zhihu.com/p/35040994 【Siamese和Ch…...

22个每个程序员都应该知道的 Git 命令

在这篇文章中&#xff0c;我写了一个快速学习 git 命令的备忘单。它将包括开发人员每天使用的命令&#xff0c;如 git add、git commit、git pull、git fetch&#xff0c;并共享其他有用的 git 命令。 我一直使用Git的一些命令&#xff0c;今天这个列表清单&#xff0c;希望也…...

Android动画——使用动画启动Activity

1、使用动画启动Activity概述 我们在Android开发应用时&#xff0c;会遇到一个页面跳转到另一个页面的情况&#xff0c;这时候我们如果使用动画过渡会使得页面更加的流畅。这是一个滑动式的进入和退出的动画可以看到Android的过渡动画可以在不同状态之间建立视觉联系。您可以为…...

【YOLO系列改进NO.46】改进激活函数为ACON

文章目录 前言一、解决问题二、基本原理三、​添加方法四、总结前言 作为当前先进的深度学习目标检测算法YOLOv7,已经集合了大量的trick,但是还是有提高和改进的空间,针对具体应用场景下的检测难点,可以不同的改进方法。此后的系列文章,将重点对YOLOv7的如何改进进行详细…...

JavaScript -- 09. 内置对象的介绍

文章目录内置对象1 解构赋值1.1 保留默认值1.2 接受剩余的所有参数1.3 对函数执行结果解构1.4 交换两个变量的值1.5 二维数组结构2 对象的解构2.1 声明对象同时解构对象2.2 先声明再解构2.3 解构不存在的属性2.4 设置解构别名2.5 设置解构默认值3 对象的序列化3.1 对象的序列化…...

Spring核心与设计思想

⭐️前言⭐️ 这篇文章作为Spring篇目的开篇&#xff0c;带领大家认识Spring&#xff0c;知道为什么要用Spring框架&#xff0c;以及了解Spring的核心与设计思想。 &#x1f349;博客主页&#xff1a; &#x1f341;【如风暖阳】&#x1f341; &#x1f349;精品Java专栏【Jav…...

Java的字符串String

文章目录什么是字符串String类的声明为什么我们的String是不可变的为什么String类用final修饰String的创建字符串比较相等关于Java中的比较关于字符串不同赋值操作对应的内存分配那对象如何进行比较内容字符串常量池StringTalbe的位置字符串常见的操作拼接操作获得字符串的子串…...

net-java-php-python-网络安全教育学习网站计算机毕业设计程序

net-java-php-python-网络安全教育学习网站计算机毕业设计程序 net-java-php-python-网络安全教育学习网站计算机毕业设计程序本源码技术栈&#xff1a; 项目架构&#xff1a;B/S架构 开发语言&#xff1a;Java语言 开发软件&#xff1a;idea eclipse 前端技术&#xff1a;…...

git分支详解——记住这些指令能帮助你解决大部分git的分支问题

Github 之 分支 branch 操作之 查看分支/创建分支/切换分支/提交分支/删除分支/合并分支 等操作 一、简单介绍 二、查看分支 1、查看本地所有分支&#xff1a;git branch 2、查看远程有哪些分支&#xff1a;git branch -r 3、查看所有分支&#xff08;本地和远程的&#xff09;…...

jdk11新特性——JShell交互性工具

目录一、jshell概述二、jshell位置三、jshell示例3.1、示例一&#xff08;声明变量并赋值&#xff09;3.2、示例二&#xff08;输出打印内容&#xff09;3.3、示例三&#xff08;帮助命令&#xff09;一、jshell概述 java9引入了jshell这个交互性工具&#xff0c;让Java也可以…...

Git全套,从简到细

Git DravenGit一、git工具引入二、git本地工具2.1、下载2.2、使用2.3、修改2.4、查看历史版本2.5、回退历史版本2.6、起死回生三、git远程仓库3.1、使用gitee3.2、配置本地仓库参数3.3、查看gitee仓库3.4、修改后推送四、git两人协作-非冲突小智小杨五、git两人协作-冲突六、gi…...

【分布式能源的选址与定容】基于非支配排序多目标遗传优化算法求解分布式能源的选址与定容(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客 &#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜…...

基于PHP+MySQL托管中心管理系统的设计与实现

随着在校学生人数的不断增加,学生的数量也在不断的增加,但是很多时候因为父母工作忙没时间,以及一些其他的原因没办法对学生间辅导,这就诞生了托管中心这一行业,但是传统的托管中心多是人工手动的模式进行管理的,这很不科学也不合理,为了改变这一现状,我们开发了托管中心管理系…...

【算法】排序——直接排序

内部排序的全部过程都是在内存中进行的。按排序策略的不同可以将内部排序划分为直接插入排序、冒泡排序、简单选择排序、希尔排序、快速排序、堆排序、归并排序、基数排序等。其中前三种排序方法属于简单的排序方法&#xff0c;其特点是排序过程直观、易于理解和实现&#xff0…...

华为高级技术专家多年经验分享微服务治理体系、架构及实践文档

前言 都说程序员工资高、待遇好&#xff0c; 2022 金九银十到了&#xff0c;你的小目标是 30K、40K&#xff0c;还是 16薪的 20K&#xff1f;作为一名 Java 开发工程师&#xff0c;当能力可以满足公司业务需求时&#xff0c;拿到超预期的 Offer 并不算难。然而&#xff0c;提升…...

HTML+CSS网页设计期末课程大作业 【茶叶文化网站设计题材】web前端开发技术 web课程设计 网页规划与设计

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…...

数据结构与算法(六) 贪心算法

这篇文章来讲贪心算法&#xff08;Greedy Algorithm&#xff09;&#xff0c;这是一种特殊的动态规划算法 1、本质 我们在之前的文章中讲过&#xff0c;动态规划可以解决一类具有最优子结构和重叠子问题特征的问题 贪心算法本质上是一种特殊的动态规划算法&#xff0c;因此在…...

LeetCode-1774. 最接近目标价格的甜点成本【数组,背包问题,优化暴力,回溯】

LeetCode-1774. 最接近目标价格的甜点成本【数组&#xff0c;背包问题&#xff0c;优化暴力&#xff0c;回溯】题目描述&#xff1a;解题思路一&#xff1a;转化为0-1背包求解。一&#xff1a;因为每种配料最多可以用两次&#xff0c;所以直接把每种辅料变成两个。二&#xff1…...

Python封装机制及实现方法

大部分语言都具备 3 个典型特征&#xff0c;即封装、继承和多态。 简单的理解封装&#xff08;Encapsulation&#xff09;&#xff0c;即在设计类时&#xff0c;刻意地将一些属性和方法隐藏在类的内部&#xff0c;这样在使用此类时&#xff0c;将无法直接以“类对象.属性名”&…...

Flet 教程大全合集

Flet是什么 Flet 是一个框架,使您能够轻松地以您喜欢的语言构建实时 Web、移动和桌面应用程序,并与您的团队安全地共享它们。无需前端经验。 Flet有什么优势 Flet有什么特点 在几分钟内从想法到应用程序 用于您的团队、周末项目、数据输入表单、信息亭应用程序或高保真原型…...

JAVA毕业设计140—基于Java+Springboot+Vue的景区旅游购票管理系统(源代码+数据库+8000字文档)

毕设所有选题&#xff1a; https://blog.csdn.net/2303_76227485/article/details/131104075 基于JavaSpringbootVue的景区旅游购票管理系统(源代码数据库8000字文档)140 一、系统介绍 本项目前后端分离&#xff0c;分为管理员、用户两种角色 1、用户&#xff1a; 注册登录…...

GPU型号-CUDA toolkit版本-driver驱动版本-VStudio版本

根据GPU型号确定可使用的CUDA版本进而确定其他软件的版本对深度学习、高性能并行计算都有重要的参考价值。鉴于互联网资料在此方面的总结较少&#xff0c;根据自身经验简单介绍版本之间的对应关系。 首先用户可以确定的是自己的GPU型号。根据自己的GPU型号可以确定该GPU对应的…...

谁考了第k名C++

题目描述 在一次考试中&#xff0c;每个学生的成绩都不相同&#xff0c;现知道了每个学生的学号和成绩&#xff0c;求考第k名学生的学号和成绩。&#xff08;按成绩从大到小排列&#xff09; 输入 第一行有两个整数&#xff0c;分别是学生的人数n&#xff08;1≤n≤100&…...

Mybatis plus update PG json 类型 报错解决

Mybatis plus update PG json 类型 报错解决 1. 定义的PG数据库对象2. 自定义 JSON Handler3. update Wrapper4. update 报错信息4.1 No hstore extension installed.4.2 Error setting non null for parameter #1 with JdbcType null . Try setting a different JdbcType for …...

车载电子电器架构 —— Vector对于车载以太网的解决方案(协议栈)

车载电子电器架构 —— Vector对于车载以太网的解决方案(协议栈) 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你…...

从油猴脚本管理器的角度审视Chrome扩展

从油猴脚本管理器的角度审视Chrome扩展 在之前一段时间&#xff0c;我需要借助Chrome扩展来完成一个需求&#xff0c;当时还在使用油猴脚本与浏览器扩展之间调研了一波&#xff0c;而此时恰好我又有一些做的还可以的油猴脚本TKScript (点个star吧 &#x1f601;)&#xff0c;相…...

python 获取最大值对应的字典

造数据 s AABBBCCCDDDDDDDDEEEFGGHHHHIJKLMMM dict_s {k:s.count(k) for k in s} print(dict_s)--->{A: 2, B: 3, C: 3, D: 8, E: 3, F: 1, G: 2, H: 4, I: 1, J: 1, K: 1, L: 1, M: 3} 一、获取最大值对应的字典方法一&#xff0c;使用zip()函数与max函数结合 zip(dict…...

iOS 键盘相关

1.键盘出现消失时&#xff0c;参考的view变化的代码&#xff1a; (void)viewDidLoad { [superviewDidLoad]; // Do any additional setup after loading the view. __weaktypeof(self) weakSelf self; _textField [UITextField new]; _textField.backgroundColor [UICol…...

No known conditions for “./lib/locale/lang/zh-cn“ entry in “element-plus“ pa

yarn的安装和卸载 npm install -g yarn npm uninstall yarn -g //yarn卸载 改用yarn卸载试试 先安装yarn npm install -g yarn 卸载掉原来的element-plus yarn remove element-plus 重新安装原有的element-plus版本 yarn add element-plus2.3.1 低版本页面引用为 i…...

Redis缓存双删(使用Redis如何保证数据库和缓存之间的同步)

使用Redis如何保证数据库和缓存之间的同步 通常我们有以下几种策略&#xff1a; 先修改数据库再更新缓存&#xff08;不建议&#xff09;&#xff1a;该策略的问题是如果数据库更新成功了Redis 修改失败了&#xff0c;也会导致不同步的问题 先修改缓存再更新数据库&#xff0…...

重学java 37.多线程基本了解

尽管走自己的路&#xff0c;别被那些三言两语击倒 —— 24.5.13 一、多线程_线程和进程 进程&#xff1a;在内存中执行的应用程序 线程:是进程中最小的执行单元线程作用:负责当前进程中程序的运行,一个进程中至少有一个线程,一个进程还可以有多个线程,这…...

RelationMap图谱--VUE,真实项目提供mock数据

RelationMap官网&#xff1a; 在线配置官网&#xff08;可以把数据放进去&#xff0c;直接看效果&#xff09; VUE2 效果&#xff1a;左侧列表栏&#xff0c;点击右侧显示对应的图谱 代码&#xff1a;按照代码直接贴过去&#xff0c;直接出效果 relationMap/index.vue <te…...