BP神经网络详解,Python实现求解异或问题

news/2024/4/20 0:33:09/文章来源:https://blog.csdn.net/Real_Fool_/article/details/127098509

BP神经网络

符号及其含义

  • nln_lnl表示第lll层神经元的个数;
  • f(⋅)f(·)f()表示神经元的激活函数;
  • W(l)∈Rni∗ni−1W^{(l)}\in\mathbb R^{n_i*n_{i-1}}W(l)Rnini1表示第l−1l-1l1层到第lll层的权重矩阵;
  • wij(l)w_{ij}^{(l)}wij(l)是权重矩阵W(l)W^{(l)}W(l)中的元素,表示第l−1l-1l1层第jjj个神经元到第lll层第iii个神经元的连接的权重(注意标号的顺序);
  • b(l)=(b1(l),b2(l),...,bnl(l))T∈R(nl)b^{(l)}=(b_1^{(l)},b_2^{(l)},...,b_{nl}^{(l)})^T\in\mathbb R^{(nl)}b(l)=(b1(l),b2(l),...,bnl(l))TR(nl)表示l−1l-1l1层到第lll层的偏置;
  • z(l)=(z1(l),z2(l),...,znl(l))T∈R(nl)z^{(l)}=(z_1^{(l)},z_2^{(l)},...,z_{nl}^{(l)})^T\in\mathbb R^{(nl)}z(l)=(z1(l),z2(l),...,znl(l))TR(nl)表示lll层神经元的状态;
  • a(l)=(a1(l),a2(l),...,anl(l))T∈R(nl)a^{(l)}=(a_1^{(l)},a_2^{(l)},...,a_{nl}^{(l)})^T\in\mathbb R^{(nl)}a(l)=(a1(l),a2(l),...,anl(l))TR(nl)表示lll层神经元的激活值(即输出值)。

在这里插入图片描述

图1图11
显然,图1所示神经网络的第2层神经元的状态及激活值可以通过下面的计算得到:
z1(2)=w11(2)x1+w12(2)x2+w13(2)x3+b1(2)z_1^{(2)}=w_{11}^{(2)}x_1+w_{12}^{(2)}x_2+w_{13}^{(2)}x_3+b_1^{(2)}z1(2)=w11(2)x1+w12(2)x2+w13(2)x3+b1(2)
z2(2)=w21(2)x1+w22(2)x2+w23(2)x3+b2(2)z_2^{(2)}=w_{21}^{(2)}x_1+w_{22}^{(2)}x_2+w_{23}^{(2)}x_3+b_2^{(2)}z2(2)=w21(2)x1+w22(2)x2+w23(2)x3+b2(2)
z3(2)=w31(2)x1+w32(2)x2+w33(2)x3+b3(2)z_3^{(2)}=w_{31}^{(2)}x_1+w_{32}^{(2)}x_2+w_{33}^{(2)}x_3+b_3^{(2)}z3(2)=w31(2)x1+w32(2)x2+w33(2)x3+b3(2)
a1(2)=f(z1(2))a_1^{(2)}=f(z_1^{(2)})a1(2)=f(z1(2))
a2(2)=f(z2(2))a_2^{(2)}=f(z_2^{(2)})a2(2)=f(z2(2))
a3(2)=f(z3(2))a_3^{(2)}=f(z_3^{(2)})a3(2)=f(z3(2))
(1)(1)(1)
类似地,第3层神经元的状态及激活值可以通过下面的计算得到:
z1(3)=w11(3)a1(2)+w12(3)a2(2)+w13(3)a3(2)+b1(3)z_1^{(3)}=w_{11}^{(3)}a_1^{(2)}+w_{12}^{(3)}a_2^{(2)}+w_{13}^{(3)}a_3^{(2)}+b_1^{(3)}z1(3)=w11(3)a1(2)+w12(3)a2(2)+w13(3)a3(2)+b1(3)
z2(3)=w21(3)a1(2)+w22(3)a2(2)+w23(3)a3(2)+b2(3)z_2^{(3)}=w_{21}^{(3)}a_1^{(2)}+w_{22}^{(3)}a_2^{(2)}+w_{23}^{(3)}a_3^{(2)}+b_2^{(3)}z2(3)=w21(3)a1(2)+w22(3)a2(2)+w23(3)a3(2)+b2(3)
a1(3)=f(z1(3))a_1^{(3)}=f(z_1^{(3)})a1(3)=f(z1(3))
a2(3)=f(z2(3))a_2^{(3)}=f(z_2^{(3)})a2(3)=f(z2(3))
(2)(2)(2)
可总结出,第l(2<=l<=L)l(2<=l<=L)l(2<=l<=L)层神经元的状态及激活值为(下面式子是向量表示形式):
z(l)=W(l)a(l−1)+b(l)(3)z^{(l)}=W^{(l)}a^{(l-1)}+b^{(l)}\\(3)z(l)=W(l)a(l1)+b(l)(3)

对于训练的数据集,使用均方误差作为损失函数来评估整体误差:
Error=12[(y1−a1(3))2+(y2−a2(3))2]Error=\frac{1}{2}\begin{bmatrix} (y_1-a_1^{(3)})^2+(y_2-a_2^{(3)})^2 \end{bmatrix}Error=21[(y1a1(3))2+(y2a2(3))2]
(4)(4)(4)
EEE展开到隐藏层:
E=12[(y1−a1(3))2+(y2−a2(3))2]E=\frac{1}{2}\begin{bmatrix} (y_1-a_1^{(3)})^2+(y_2-a_2^{(3)})^2 \end{bmatrix}E=21[(y1a1(3))2+(y2a2(3))2]
E=12[(y1−f(z1(3)))2+(y2−f(z2(3)))2]E=\frac{1}{2}\begin{bmatrix} (y_1-f(z_1^{(3)}))^2+(y_2-f(z_2^{(3)}))^2 \end{bmatrix}E=21[(y1f(z1(3)))2+(y2f(z2(3)))2]
E=12[(y1−f(w11(3)a1(2)+w12(3)a2(2)+w13(3)a3(2)+b1(3)))2+(y2−f(w21(3)a1(2)+w22(3)a2(2)+w23(3)a3(2)+b2(3)))2]E=\frac{1}{2}\begin{bmatrix} (y_1-f(w_{11}^{(3)}a_1^{(2)}+w_{12}^{(3)}a_2^{(2)}+w_{13}^{(3)}a_3^{(2)}+b_1^{(3)}))^2+(y_2-f(w_{21}^{(3)}a_1^{(2)}+w_{22}^{(3)}a_2^{(2)}+w_{23}^{(3)}a_3^{(2)}+b_2^{(3)}))^2 \end{bmatrix}E=21[(y1f(w11(3)a1(2)+w12(3)a2(2)+w13(3)a3(2)+b1(3)))2+(y2f(w21(3)a1(2)+w22(3)a2(2)+w23(3)a3(2)+b2(3)))2]
(5)(5)(5)
我们的目的时调整权重和偏执使总体误差减小,求得误差为最小(或某一可以接受的范围)时所对应的每个wij(l)w_{ij}^{(l)}wij(l)bi(l)b_i^{(l)}bi(l)
训练过程的核心就是梯度下降,我们对每个参数wij(l)w_{ij}^{(l)}wij(l)bi(l)b_i^{(l)}bi(l)求偏导,通过下降这些梯度来减小损失函数EEE的值,每次步长为α\alphaα(学习率),这也就是每个权重的更新过程,以w11(3)w_{11}^{(3)}w11(3)为例:
w11(3)w_{11}^{(3)}w11(3)为例,由链式求导法则,对w11(3)w_{11}^{(3)}w11(3)求偏导结果为:
∂E∂w11(3)=∂E∂z1(3)∂z1(3)∂w11(3)=∂E∂a1(3)∂a1(3)∂z1(3)∂z1(3)∂w11(3)=−(y1−a1(3))f′(z1(3))∂z1(3)∂w11(3)=−(y1−a1(3))f′(z1(3))a1(2)\frac{\partial E}{\partial w_{11}^{(3)}} = \frac{\partial E}{\partial z_{1}^{(3)}} \frac{\partial z_{1}^{(3)}}{\partial w_{11}^{(3)}} = \frac{\partial E}{\partial a_{1}^{(3)}} \frac{\partial a_{1}^{(3)}}{\partial z_{1}^{(3)}}\frac{\partial z_{1}^{(3)}}{\partial w_{11}^{(3)}} = -(y_1-a_1^{(3)})f^{'}(z_1^{(3)}) \frac{\partial z_{1}^{(3)}}{\partial w_{11}^{(3)}} = -(y_1-a_1^{(3)})f^{'}(z_1^{(3)}) a_1^{(2)}w11(3)E=z1(3)Ew11(3)z1(3)=a1(3)Ez1(3)a1(3)w11(3)z1(3)=(y1a1(3))f(z1(3))w11(3)z1(3)=(y1a1(3))f(z1(3))a1(2)
(6)(6)(6)
其中偏导数∂E∂zi(l)\frac{\partial E}{\partial z_{i}^{(l)}}zi(l)E表示第lll层第iii个神经元对最终损失的影响,也反映了最终损失对第lll层神经元的敏感程度,因此一般称为第lll层神经元的误差项,用δ(l)\delta^{(l)}δ(l)来表示。
δ(l)≡∂E∂zi(l)(7)\delta^{(l)}≡\frac{\partial E}{\partial z_{i}^{(l)}}\\(7)δ(l)zi(l)E(7)
∂E∂w11(3)=∂E∂z1(3)∂z1(3)∂w11(3)=δ1(3)a1(2)(8)\frac{\partial E}{\partial w_{11}^{(3)}} = \frac{\partial E}{\partial z_{1}^{(3)}} \frac{\partial z_{1}^{(3)}}{\partial w_{11}^{(3)}}=\delta_1^{(3)}a_1^{(2)}\\(8)w11(3)E=z1(3)Ew11(3)z1(3)=δ1(3)a1(2)(8)
其中:δ1(3)=∂E∂z1(3)=∂E∂a1(3)∂a1(3)∂z1(3)=−(y1−a1(3))f′(z1(3))\delta_1^{(3)}= \frac{\partial E}{\partial z_{1}^{(3)}}= \frac{\partial E}{\partial a_{1}^{(3)}} \frac{\partial a_{1}^{(3)}}{\partial z_{1}^{(3)}} =-(y_1-a_1^{(3)})f^{'}(z_1^{(3)})δ1(3)=z1(3)E=a1(3)Ez1(3)a1(3)=(y1a1(3))f(z1(3))

对于误差项δ\deltaδ(增量),引入他除了可以简化计算∂E∂w\frac{\partial E}{\partial w}wE以外,更重要的是可以通过δ(l+1)\delta^{(l+1)}δ(l+1)来求解δ(l)\delta^{(l)}δ(l),这样可以便于理解和加快计算速度。

以下是输出层(L)(L)(L)计算误差项和梯度的矩阵形式(⊙表示矩阵中对应位置元素相乘)
δ(L)=−(y−a(L))⊙f′(z(L))△w(L)=δ(l)(a(L−1))T(9)\delta^{(L)}=-(y-a^{(L)})⊙f^{'}(z^{(L)})\\△w^{(L)}=\delta^{(l)}(a^{(L-1)})^T\\(9)δ(L)=(ya(L))f(z(L))w(L)=δ(l)(a(L1))T(9)
权重更新公式(α为学习率\alpha为学习率α):
w(L)=w(L)−α△w(L)(10)w^{(L)}=w^{(L)}-\alpha△w^{(L)}\\(10)w(L)=w(L)αw(L)(10)
再以隐藏层的w11(2)w_{11}^{(2)}w11(2)为例,按照链式求导规则可以展开为两项和:
∂E∂w11(2)=∂E∂a1(3)∂a1(3)∂z1(3)∂z1(3)∂a1(2)∂a1(2)∂z1(2)∂z1(2)∂w11(2)+∂E∂a2(3)∂a2(3)∂z2(3)∂z2(3)∂a1(2)∂a1(2)∂z1(2)∂z1(2)∂w11(2)=−(y−a1(3))f′(z1(3))w11(3)f′(z1(2))x1−(y−a2(3))f′(z2(3))w21(3)f′(z1(2))x1=[(y−a1(3))f′(z1(3))w11(3)−(y−a2(3))f′(z2(3))w21(3)]f′(z1(2))x1=(δ1(3)w11(3)+δ2(3)w21(3))f′(z1(2))x1\frac{\partial E}{\partial w_{11}^{(2)}} \\ = \frac{\partial E}{\partial a_{1}^{(3)}} \frac{\partial a_{1}^{(3)}}{\partial z_{1}^{(3)}} \frac{\partial z_{1}^{(3)}}{\partial a_{1}^{(2)}} \frac{\partial a_{1}^{(2)}}{\partial z_{1}^{(2)}} \frac{\partial z_{1}^{(2)}}{\partial w_{11}^{(2)}} + \frac{\partial E}{\partial a_{2}^{(3)}} \frac{\partial a_{2}^{(3)}}{\partial z_{2}^{(3)}} \frac{\partial z_{2}^{(3)}}{\partial a_{1}^{(2)}} \frac{\partial a_{1}^{(2)}}{\partial z_{1}^{(2)}} \frac{\partial z_{1}^{(2)}}{\partial w_{11}^{(2)}}\\ = -(y-a_1^{(3)})f^{'}(z_1^{(3)})w_{11}^{(3)}f^{'}(z_1^{(2)})x1 - (y-a_2^{(3)})f^{'}(z_2^{(3)})w_{21}^{(3)}f^{'}(z_1^{(2)})x1\\ =\begin{bmatrix} (y-a_1^{(3)})f^{'}(z_1^{(3)})w_{11}^{(3)} - (y-a_2^{(3)})f^{'}(z_2^{(3)})w_{21}^{(3)} \end{bmatrix} f^{'}(z_1^{(2)})x1\\ =(\delta_1^{(3)}w_{11}^{(3)}+\delta_2^{(3)}w_{21}^{(3)})f^{'}(z_1^{(2)})x1w11(2)E=a1(3)Ez1(3)a1(3)a1(2)z1(3)z1(2)a1(2)w11(2)z1(2)+a2(3)Ez2(3)a2(3)a1(2)z2(3)z1(2)a1(2)w11(2)z1(2)=(ya1(3))f(z1(3))w11(3)f(z1(2))x1(ya2(3))f(z2(3))w21(3)f(z1(2))x1=[(ya1(3))f(z1(3))w11(3)(ya2(3))f(z2(3))w21(3)]f(z1(2))x1=(δ1(3)w11(3)+δ2(3)w21(3))f(z1(2))x1 (12)(12)(12)

又因为:
∂E∂w11(2)=∂E∂z1(2)∂z1(2)∂w11(2)=δ1(2)x1\frac{\partial E}{\partial w_{11}^{(2)}} = \frac{\partial E}{\partial z_{1}^{(2)}} \frac{\partial z_{1}^{(2)}}{\partial w_{11}^{(2)}} = \delta_1^{(2)}x_1w11(2)E=z1(2)Ew11(2)z1(2)=δ1(2)x1 (13)(13)(13)
(12)(13)(12)(13)(12)(13)可得:
∂E∂w11(2)=(δ1(3)w11(3)+δ2(3)w21(3))f′(z1(2))x1=δ1(2)x1\frac{\partial E}{\partial w_{11}^{(2)}}\\ =(\delta_1^{(3)}w_{11}^{(3)}+\delta_2^{(3)}w_{21}^{(3)})f^{'}(z_1^{(2)})x1\\ =\delta_1^{(2)}x_1w11(2)E=(δ1(3)w11(3)+δ2(3)w21(3))f(z1(2))x1=δ1(2)x1

从以上公式可以看出,第lll层的误差项可以通过第l+1l+1l+1层的误差项计算得到,这就是误差的反向传播。
反向传播算法的含义是:第lll层的一个神经元的误差项是所有与该神经元相连的第l+1l+1l+1层的神经元的误差项的权重和。然后,再乘上该神经元激活函数的梯度。
以矩阵的形式可以写为:
δ(l)=((W(l+1))Tδ(l+1))⊙f′(z(l))△w(L)=δ(L)XT(14)\delta^{(l)}=((W^{(l+1)})^T\delta^{(l+1)})⊙f^{'}(z^{(l)})\\ △w^{(L)}=\delta^{(L)}X^T\\ (14)δ(l)=((W(l+1))Tδ(l+1))f(z(l))w(L)=δ(L)XT(14)

Python实现BP求解异或问题

# -*- coding: utf-8 -*-
import numpy as np# 双曲正切函数,该函数为奇函数
def tanh(x):return np.tanh(x)# tanh导函数性质:f'(t) = 1 - f(x)^2
def tanh_prime(x):return 1.0 - tanh(x) ** 2class NeuralNetwork:def __init__(self, layers, activation='tanh'):""":参数layers: 神经网络的结构(输入层-隐含层-输出层包含的结点数列表):参数activation: 激活函数类型"""if activation == 'tanh':  # 也可以用其它的激活函数self.activation = tanhself.activation_prime = tanh_primeelse:pass# 存储权值矩阵self.weights = []# range of weight values (-1,1)# 初始化输入层和隐含层之间的权值print('------------------', len(layers))    # 3for i in range(1, len(layers) - 1):# layer[i-1]+1 = layer[0]+1 = 2+1 = 3# layers[i] + 1 = layer[1]+1 = 3r = 2 * np.random.random((layers[i - 1] + 1, layers[i] + 1)) - 1  # add 1 for bias nodeself.weights.append(r)# 初始化输出层权值r = 2 * np.random.random((layers[i] + 1, layers[i + 1])) - 1self.weights.append(r)def fit(self, X, Y, learning_rate=0.2, epochs=10000):# 将一列一加到X# 这是为了将偏置单元添加到输入层# np.hstack()将两个数组按水平方向组合起来, 4*2 --> 4*3X = np.hstack([np.ones((X.shape[0], 1)), X])for k in range(epochs):  # 训练固定次数# if k % 1000 == 0: print('epochs:', k)# 从区间中的离散均匀分布返回随机整数 [0, low).[0, 4)i = np.random.randint(X.shape[0], high=None)a = [X[i]]  # 从m个输入样本中随机选一组# len(self.weights) 2for l in range(len(self.weights)):# 每组输入样本(第一列未偏执值b)与权值进行矩阵相乘,a:1*3, weights:3*3 ---> 1*3dot_value = np.dot(a[l], self.weights[l])  # 权值矩阵中每一列代表该层中的一个结点与上一层所有结点之间的权值activation = self.activation(dot_value)     # 放入激活函数a.append(activation)'''反向传播算法的含义是:第l层的一个神经元的误差项delta(l)是所有与该神经元相连的第l+1层的神经元的误差项delta(l+1)的权重和。然后,再乘上该神经元激活函数的梯度。'''# 均方误差函数   E = 1/2 * (Y - a)**2# 反向递推计算delta:从输出层开始,先算出该层的delta,再向前计算error = Y[i] - a[-1]  # 计算输出层deltadeltas = [error * self.activation_prime(a[-1])]# 从倒数第2层开始反向计算deltafor l in range(len(a) - 2, 0, -1):deltas.append(deltas[-1].dot(self.weights[l].T) * self.activation_prime(a[l]))# [level3(output)->level2(hidden)]  => [level2(hidden)->level3(output)]deltas.reverse()  # 逆转列表中的元素# backpropagation# 1. 将其输出增量与输入激活相乘,得到权重的梯度。# 2. 从权重中减去渐变的比率(百分比)。for i in range(len(self.weights)):  # 逐层调整权值layer = np.atleast_2d(a[i])  # 将输入作为至少具有两个维度的数组查看delta = np.atleast_2d(deltas[i])self.weights[i] += learning_rate * np.dot(layer.T, delta)  # 每输入一次样本,就更新一次权值def predict(self, x):a = np.concatenate((np.ones(1), np.array(x)))  # a为输入向量(行向量)for l in range(0, len(self.weights)):  # 逐层计算输出a = self.activation(np.dot(a, self.weights[l]))return aif __name__ == '__main__':nn = NeuralNetwork([2, 2, 1])  # 网络结构: 2输入1输出,1个隐含层(包含2个结点)X = np.array([[0, 0],  # 输入矩阵(每行代表一个样本,每列代表一个特征)[0, 1],[1, 0],[1, 1]])Y = np.array([0, 1, 1, 0])  # 期望输出nn.fit(X, Y)  # 训练网络print('w:', nn.weights)  # 调整后的权值列表for s in X:print(s, nn.predict(s))  # 测试

运行结果:

在这里插入图片描述

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

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

相关文章

idea手动创建webapp(在main文件夹下)

SSM自学笔记 文章目录一、Maven使用正常情况首先不使用骨架创建好Maven项目然后选择Project Structure...选择要创建webapp的模块修改路径二、Maven不正常工作时一、Maven使用正常情况 首先不使用骨架创建好Maven项目 然后选择Project Structure… 选择要创建webapp的模块 选好…

python数据容器——列表

目录 一.数据容器 二.数据容器——列表 基本语法 注意 三.列表的下标&#xff08;索引&#xff09; 嵌套列表的下标&#xff08;索引&#xff09; 四.列表的常用操作&#xff08;方法&#xff09; 1.查询元素下标 2.插入元素 3.删除元素 4.统计元素 说明 一.数据容器 1&a…

传奇出现黑屏卡屏不动是怎么回事

在写这篇文章之前&#xff0c;先给给大家说一下&#xff0c;这篇文章写的是出现黑屏、卡屏不动是我们玩传奇的时候出现的&#xff0c;而不是在架设传奇时候出现的&#xff0c;所以要特别是注意一下&#xff0c;架设和玩出现黑屏是完全不一样的&#xff0c;所以解决方案也不一样…

H3C opsf/rip/ftp/telent/nat/acl综合

实验拓扑 拓扑下载 https://sharewh2.xuexi365.com/share/84b85b32-acb7-4f62-a389-6188680a19f3?t3 图 1-1 注&#xff1a;如无特别说明&#xff0c;描述中的 R1 或 SW1 对应拓扑中设备名称末尾数字为 1 的设备&#xff0c;R2 或 SW2 对应拓扑中设备名称末尾数字为 2 的设备…

【jmeter】windows下使用 (测试MQTT)

1. 添加线程组 二、添加如下请求 1. 添加创建连接请求-选中线程组&#xff0c; 点击右键&#xff0c;添加>取样器>MQTT Connect设置MQTT连接 本次使用本机开启的MQTT服务进行测试&#xff0c;默认ip为127.0.0.1&#xff0c;端口默认1883 2. 添加发布请求-选中线程组 …

软件测试之对于测试的反思及思考

1.针对一个页面&#xff0c;从页面的完整性(包括字段、输入框、功能点)出发 2.对于分页&#xff0c;考虑未在首页的时候的测试&#xff0c;末页的情况。 3.对条件的查询来说&#xff0c;要针对于单个输入框的测试、交叉输入框的测试 4.对于删除、修改等&#xff0c;要考虑你删除…

nablet Elements released处理视频的组件

nablet Elements released处理视频的组件 mediaEngine-一个转码工厂&#xff0c;为视频工作流从贡献到分发提供动力。 HeightScreen-AI驱动的工具&#xff0c;用于将视频转换为垂直屏幕&#xff0c;自动选择感兴趣的区域。 Shrynk-AI驱动的解决方案&#xff0c;可自动完成高亮编…

【站内题解】十六道csdn每日一练Python题解

文章目录题目一&#xff1a; 游乐园的门票1. 问题描述2. 输入描述3. 输出描述4. 示例4.1 输入4.2 输出5. 答案5.1 解法一5.2 解法二题目二&#xff1a;小桥流水人家1. 问题描述2. 输入描述3. 输出描述4. 示例4.1 输入4.2 输出5. 答案题目三&#xff1a;小艺读书1. 问题描述2. 输…

Wordpress模板主题中functions.php常用功能代码与常用插件(持续收集整理)

用Wordpress建站的初学者一定会需要用到的Wordpress模板主题中functions.php常用功能代码与常用插件。慢慢持续收集整理....... 目录 一、Wordpress模板主题中functions文件常用的代码 二、Wordpress自定义字段的设定与调用代码&#xff08;系统常规自定义字段&#xff09; …

ESP32基础应用之LVGL基础

文章目录1 实验目的1.1 参考文章2 实验工具3 准备工作3.1 搭建ESP32开发环境3.2 克隆lv_port_esp32工程4 配置lv_port_esp32工程5 实验验证6 使用过程遇到的问题6.1 触摸功能点击屏幕位置不对1 实验目的 本实验为使用ESP32实现LVGL&#xff08;轻量级的嵌入式图形库&#xff0…

消息队列概述与扩展

一、消息队列的特性 与业务解藕&#xff1a;一个具有普适性质的消息队列组件不需要考虑上层的业务模型&#xff0c;只做好消息的分发就可以了&#xff0c;上层业务的不同模块反而需要依赖消息队列所定义的规范进行通信。FIFO&#xff1a;先投递先到达的保证是一个消息队列和一…

计算机组成原理习题课第三章-2(唐朔飞)

计算机组成原理习题课第三章-2&#xff08;唐朔飞&#xff09; ✨欢迎关注&#x1f5b1;点赞&#x1f380;收藏⭐留言✒ &#x1f52e;本文由京与旧铺原创&#xff0c;csdn首发&#xff01; &#x1f618;系列专栏&#xff1a;java学习 &#x1f4bb;首发时间&#xff1a;&…

梦开始的地方——C语言柔性数组

文章目录柔性数组什么是柔性数组&#xff1f;柔性数组的使用柔性数组的优点柔性数组 什么是柔性数组&#xff1f; 在C99中&#xff0c;结构体最后一个元素它允许是一个未知大小的数组&#xff0c;这就叫做柔性数组成员。 这个概念听起来可能有点不可以思议&#xff0c;但它的…

第三十九篇 自定义指令 - directive

前面讲了关于在Vue中如何来进行封装swiper组件的内容&#xff0c;本篇内容讲到使自定义组件&#xff0c;讲这块内容也是同样为了后续再次回顾封装swiper组件变化做铺垫内容&#xff0c;那么什么是自定义指令&#xff0c;在前面的内容讲过了好些常用的指令&#xff0c;如 v-modl…

【linux】环境基础开发工具使用

1.vim编辑器 vim中最常用的是三种模式&#xff1a;命令模式&#xff0c;底行模式&#xff0c;插入模式。 命令模式(Normal mode)命令模式是我们第一次vim打开文件的样子&#xff08;默认模式&#xff09;&#xff0c;这里控制屏幕光标的移动&#xff0c;字符、字或行的删除&…

考CISAW的N个理由!

随着信息科技的飞速发展&#xff0c;互联网的普及&#xff0c;面对信息安全的严峻局势&#xff0c;网络信息安全显得尤为重要&#xff0c;同时近些年来&#xff0c;国家也相继出台一些政策&#xff0c;并推出一些国家认证的资格证书&#xff0c;CISAW认证就是专门针对信息安全保…

DPDK代码目录结构

DPDK功能结构 DPDK工程目录内容 dpdk-stable-18.11.11]# ls app buildtools devtools drivers GNUmakefile lib MAINTAINERS meson.build mk README usertools build config doc examples kernel license Makefile meson_opt…

使用React.ts创建一个密码生成器的简单示例

目录密码生成器DemoFeature知识点React TypeScript —— Function Components为元素(::before/::after)绑定点击事件React如何正确定义对象数组在React中设置复选框check属性三目运算符实现React动态绑定class和style参考资料密码生成器Demo 使用密码生成器工具创建随机密码。P…

GIT技巧

目录 基础命令 commit 、branch merge rebase 高级特性 自由修改提交树 cherry-pick rebase 远程仓库命令 基础命令 commit 、branch Git Commit Git 仓库中的提交记录保存的是你的目录下所有文件的快照&#xff0c;就像是把整个目录复制&#xff0c;然后再粘贴一样…

流媒体传输 - HLS 协议

HLS 全称是 HTTP Live Streaming&#xff0c;是一个由 Apple 公司提出的基于 HTTP 的媒体流传输协议&#xff0c;用于实时音视频流的传输。目前 HLS 协议被广泛的应用于视频点播和直播领域。 概述 原理介绍 通过将整条流切割成一个小的可以通过 HTTP 下载的媒体文件&#xff…