深度学习 | 前馈神经网络与反向传播算法

目录

一、Logistic函数

二、前馈神经网络(FNN)

三、反向传播算法(BP算法)

​四、基于前馈神经网络的手写体数字识别


一、Logistic函数

Logistic函数是学习前馈神经网络的基础。所以在介绍前馈神经网络之前,我们首先来看一看Logistic函数。

Logistic函数定义为:

\sigma \left ( x \right )=\frac{1}{1+exp\left ( -x \right )}

Logistic函数可以看成是一个“挤压”函数, 把一个实数域的输入“挤压”到(0,1)。当输入值在0附近时。Sigmoid型函数近似为线性函数;当输入值靠近两侧时,对输入进行抑制。输入越小,越接近于0;输入越大,越接近于1。

这样的特点也和生物神经元类似,对一些输入会产生兴奋(输入为1),对另一些输入产生抑制(输出为0)。和感知器使用的阶跃激活函数相比,Logistic函数是连续可导的,其数学性质更好。

因为Logistic函数的性质,使得装备了Logistic激活函数的神经元具有以下两点性质:

(1)其输出直接可以看作概率分布,使得神经网络可以更好地和统计学习模型进行结合;

(2)其可以看作一个软性门,用来控制其他神经元输出信息的数量。

Logistic函数的导数为\sigma ^{'}\left ( x \right )=\sigma \left ( x \right )\left ( 1-\sigma \left ( x \right ) \right ),其推导过程如下:

\sigma \left ( x \right )=\frac{1}{1+e^{-x}}

\sigma ^{'}\left ( x \right )=\frac{e^{-x}}{\left ( 1+e^{-x} \right )^{2}}

=\frac{1+e^{-x}}{\left ( 1+e^{-x} \right )^{2}}-\frac{1}{\left ( 1+e^{-x} \right )^{2}}

=\frac{1}{1+e^{-x}}-\frac{1}{\left ( 1+e^{-x} \right )^{2}}

=\frac{1}{1+e^{-x}}\left ( 1-\frac{1}{1+e^{-x}} \right )

=\sigma \left ( x \right )\left ( 1-\sigma \left ( x \right ) \right )

Logistic函数的图像如下:

二、前馈神经网络(FNN)

前馈神经网络其实是由多层的Logistic回归模型(连续的非线性函数)组成,而不是由多层的感知器(不连续的非线性函数)组成。

在前馈神经网络中, 各神经元分别属于不同的层。每一层的神经元可以接收前一层神经元的信号,并产生信号输出到下一层。第0层称为输入层,最后一层称为输出层,其他中间层称为隐藏层。整个网络中无反馈,信号从输入层向输出层单向传递,可用一个有向无环图表示。

接下来,我们以下面的一个神经网络为例,推导前馈神经网络的数学模型。

图中,a_{i}^{\left ( j \right )}代表第j层第i个神经元的活性值,\Theta ^{\left ( j \right )}代表控制激活函数从第j层映射到第j+1层的权重矩阵。 

这里的激活函数我们使用的是Logistic函数,这里我们用g(x)表示。

因此,有:

x=\begin{bmatrix} x_{0}\\ x_{1}\\ x_{2} \end{bmatrix}=a^{(1)}=\begin{bmatrix} a_{0}^{(1)}\\ a_{1}^{(1)}\\ a_{2}^{(1)} \end{bmatrix}

x_{0}=1 , a_{0}^{(1)}=1 

\Theta ^{(1)}=\begin{bmatrix} \Theta _{10}^{(1)} & \Theta _{11}^{(1)} &\Theta _{12}^{(1)} \\ \Theta _{20}^{(1)} & \Theta _{21}^{(1)} & \Theta _{22}^{(1)} \end{bmatrix} 

z_{1}^{(2)}=\Theta _{10}^{(1)}a_{0}^{(1)}+\Theta _{11}^{(1)}a_{1}^{(1)}+\Theta _{12}^{(1)}a_{2}^{(1)} 

z_{2}^{(2)}=\Theta _{20}^{(1)}a_{0}^{(1)}+\Theta _{21}^{(1)}a_{1}^{(1)}+\Theta _{22}^{(1)}a_{2}^{(1)} 

a_{1}^{(2)}=g(z_{1}^{(2)}) 

a_{2}^{(2)}=g(z_{2}^{(2)}) 

a^{(2)}=\begin{bmatrix} 1\\ a^{(2)} \end{bmatrix}=\begin{bmatrix} a_{0}^{(2)}\\ a_{1}^{(2)}\\ a_{2}^{(2)} \end{bmatrix} 

 \Theta ^{(2)}=\begin{bmatrix} \Theta _{10}^{(2)} & \Theta _{11}^{(2)} &\Theta _{12}^{(2)} \\ \Theta _{20}^{(2)} & \Theta _{21}^{(2)} & \Theta _{22}^{(2)} \end{bmatrix}

 z_{1}^{(3)}=\Theta _{10}^{(2)}a_{0}^{(2)}+\Theta _{11}^{(2)}a_{1}^{(2)}+\Theta _{12}^{(2)}a_{2}^{(2)}

z_{2}^{(3)}=\Theta _{20}^{(2)}a_{0}^{(2)}+\Theta _{21}^{(2)}a_{1}^{(2)}+\Theta _{22}^{(2)}a_{2}^{(2)}

a_{1}^{(3)}=g(z_{1}^{(3)})

a_{2}^{(3)}=g(z_{2}^{(3)})

a^{(3)}=\begin{bmatrix} 1\\ a^{(3)} \end{bmatrix}=\begin{bmatrix} a_{0}^{(3)}\\ a_{1}^{(3)}\\ a_{2}^{(3)} \end{bmatrix} 

 \Theta ^{(3)}=\begin{bmatrix} \Theta _{10}^{(3)} & \Theta _{11}^{(3)} & \Theta _{12}^{(3)} \end{bmatrix}

z_{1}^{(4)}=\Theta _{10}^{(3)}a_{0}^{(3)}+\Theta _{11}^{(3)}a_{1}^{(3)}+\Theta _{12}^{(3)}a_{2}^{(3)}

a_{1}^{(4)}=g(z_{1}^{(4)})

我们也可以将上面的公式写成向量的形式:

 z^{(2)}=\begin{bmatrix} z_{1}^{(2)}\\ z_{2}^{(2)} \end{bmatrix} , a^{(2)}=\begin{bmatrix} a_{1}^{(2)}\\ a_{2}^{(2)} \end{bmatrix}

z^{(2)}=\Theta ^{(1)}a^{(1)}

a^{(2)}=g(z^{(2)})

 z^{(3)}=\begin{bmatrix} z_{1}^{(3)}\\ z_{2}^{(3)} \end{bmatrix} , a^{(3)}=\begin{bmatrix} a_{1}^{(3)}\\ a_{2}^{(3)} \end{bmatrix}

z^{(3)}=\Theta ^{(2)}a^{(2)}

a^{(3)}=g(z^{(3)})

z^{(4)}=\begin{bmatrix} z_{1}^{(4)} \end{bmatrix} , a^{(4)}=\begin{bmatrix} a_{1}^{(4)} \end{bmatrix}

 z^{(4)}=\Theta ^{(3)}a^{(3)}

a^{(4)}=g(z^{(4)})

因此,该前馈神经网络最后的输出值为:

h_{\Theta }(x^{(i)})=a^{(4)}

                      =g(z^{(4)})

                              =g(\Theta ^{(3)}a^{(3)})

                                    =g(\Theta ^{(3)}g(z^{(3)}))

                                           =g(\Theta ^{(3)}g(\Theta ^{(2)}a^{(2)}))

                                                 =g(\Theta ^{(3)}g(\Theta ^{(2)}g(z^{(2)})))

                                                         =g(\Theta ^{(3)}g(\Theta ^{(2)}g(\Theta ^{(1)}a^{(1)}))) 

可以看出,这是一个复合函数

三、反向传播算法(BP算法)

这里,我们还是使用上面的神经网络模型:

这里,\delta _{j}^{(l)}代表第l层第j个神经元的误差。

该神经网络的损失函数为:

J(\Theta )=-\frac{1}{m}\sum_{i=1}^{m}\left [ y^{(i)}logh_{\Theta }(x^{(i)})+(1-y^{(i)})log(1-h_{\Theta }(x^{(i)})) \right ]+\frac{\lambda }{2m}\sum_{l=1}^{L-1}\sum_{i=1}^{s_{l}}\sum_{j=1}^{s_{l+1}}(\Theta _{ji}^{(l)})^{2}

这里,我们令 cost(i)=-\left [ y^{(i)}logh_{\Theta }(x^{(i)})+(1-y^{(i)})log(1-h_{\Theta }(x^{(i)})) \right ],并且有cost(i)\approx (h_{\Theta }(x^{(i)})-y^{(i)})^{2},在不考虑正则项的情况下,有:

\frac{\partial }{\partial\Theta _{ij}^{(l)} }J(\Theta )=\frac{1}{m}\frac{\partial }{\partial\Theta _{ij}^{(l)} }cost(I)

 于是,反向传播算法的推导过程如下:

首先,令

\delta _{j}^{(4)}=a_{j}^{(4)}-y_{j}=(h_{\Theta }(x))_{j}-y_{j}

\delta ^{(4)}=a^{(4)}-y(=预测值-真实值) 

根据链式求导法则有:

\frac{\partial cost(I)}{\partial \Theta _{ij}^{(3)}}=\frac{\partial cost(I)}{\partial z^{(4)}}\cdot \frac{\partial z^{(4)}}{\partial \Theta _{ij}^{(3)}}

由于 

z^{(4)}=\Theta _{10}^{(3)}a_{0}^{(3)}+\Theta _{11}^{(3)}a_{1}^{(3)}+\Theta _{12}^{(3)}a_{2}^{(3)}

 \frac{\partial z^{(4)}}{\partial \Theta _{ij}^{(3)}}=a_{j}^{(3)}

由于

cost(I)=-\left [ y^{(i)}logh_{\Theta }(x^{(i)})+(1-y^{(i)})log(1-h_{\Theta }(x^{(i)})) \right ]

\frac{\partial cost(I)}{\partial z^{(4)}}=-[y^{(i)}\cdot \frac{1}{g(z^{(4)})}g^{'}(z^{(4)})+(1-y^{(i)})\cdot \frac{1}{1-g(z^{(4)})}(-g^{'}(z^{(4)}))]

 =-[y^{(i)}\cdot \frac{1}{g(z^{(4)})}g(z^{(4)})(1-g(z^{(4)}))-(1-y^{(i)})\cdot \frac{1}{1-g(z^{(4)})}\cdot g(z^{(4)})\cdot (1-g(z^{(4)}))]

              =-[y^{(i)}(1-g(z^{(4)}))-(1-y^{(i)})\cdot g(z^{(4)})]

              =-[y^{(i)}-y^{(i)}g(z^{(4)})-g(z^{(4)})+y^{(i)}g(z^{(4)})]

              =g(z^{(4)})-y^{(i)}

              =h_{\Theta }(x^{(i)})-y^{(i)}

              =\delta ^{(4)}

因此,

\frac{\partial cost(I)}{\partial \Theta _{ij}^{(3)}}=\delta ^{(4)}a_{j}^{(3)}

接下来,我们先来推导一下\delta ^{(3)}

首先,\delta ^{(3)}=\frac{\partial cost(I)}{\partial z^{(3)}}

根据链式求导法则,有:

 \frac{\partial cost(I)}{\partial z^{(3)}}=\frac{\partial cost(I)}{\partial z^{(4)}}\cdot \frac{\partial z^{(4)}}{\partial z^{(3)}}

已知\frac{\partial cost(I)}{\partial z^{(4)}}=\delta ^{(4)}

又由于

z^{(4)}=\Theta ^{(3)}a^{(3)}=\Theta ^{(3)}g(z^{(3)}) 

故有:

\frac{\partial z^{(4)}}{\partial z^{(3)}}=\Theta ^{(3)}g^{'}(z^{(3)})

因此,有:

\delta ^{(3)}=\delta ^{(4)}\cdot \Theta ^{(3)}g^{'}(z^{(3)}) 

接着,再推导\delta ^{(2)}

 \frac{\partial cost(I)}{\partial z^{(2)}}=\frac{\partial cost(I)}{\partial z^{(4)}}\cdot \frac{\partial z^{(4)}}{\partial z^{(3)}}\cdot \frac{\partial z^{(3)}}{\partial z^{(2)}}

已知 \frac{\partial cost(I)}{\partial z^{(4)}}=\delta ^{(4)}\frac{\partial z^{(4)}}{\partial z^{(3)}}=\Theta ^{(3)}g^{'}(z^{(3)})

又由于

z^{(3)}=\Theta ^{(2)}a^{(2)}=\Theta ^{(2)}g(z^{(2)})

故有:

\frac{\partial z^{(3)}}{\partial z^{(2)}}=\Theta ^{(2)}g^{'}(z^{(2)}) 

因此,有:

\delta ^{(2)}=\delta ^{(4)}\cdot\Theta ^{(3)}g^{'}(z^{(3)})\cdot \Theta ^{(2)}g^{'}(z^{(2)})=\delta ^{(3)}\cdot \Theta ^{(2)}g^{'}(z^{(2)}) 

下面继续推导 \frac{\partial cost(I)}{\partial \Theta _{ij}^{(2)}}:

由链式求导法则有:

\frac{\partial cost(I)}{\partial \Theta _{ij}^{(2)}}=\frac{\partial cost(I)}{\partial z^{(4)}}\cdot \frac{\partial z^{(4)}}{\partial z^{(3)}}\cdot \frac{\partial z^{(3)}}{\partial \Theta _{ij}^{(2)}}

已知 \frac{\partial cost(I)}{\partial z^{(4)}}=\delta ^{(4)}\frac{\partial z^{(4)}}{\partial z^{(3)}}=\Theta ^{(3)}g^{'}(z^{(3)})

又由于

z_{1}^{(3)}=\Theta _{10}^{(2)}a_{0}^{(2)}+\Theta _{11}^{(2)}a_{1}^{(2)}+\Theta _{12}^{(2)}a_{2}^{(2)}

 z_{2}^{(3)}=\Theta _{20}^{(2)}a_{0}^{(2)}+\Theta _{21}^{(2)}a_{1}^{(2)}+\Theta _{22}^{(2)}a_{2}^{(2)}

故有:

\frac{\partial z^{(3)}}{\partial \Theta _{ij}^{(2)}}=a_{j}^{(2)}

因此, 

\frac{\partial cost(I)}{\partial \Theta _{ij}^{(2)}}=\delta ^{(4)}\cdot\Theta ^{(3)}g^{'}(z^{(3)})\cdot a_{j}^{(2)}=\delta ^{(3)}a_{j}^{(2)}

接着,继续推导\frac{\partial cost(I)}{\partial \Theta _{ij}^{(1)}}

由链式求导法则有:

\frac{\partial cost(I)}{\partial \Theta _{ij}^{(1)}}=\frac{\partial cost(I)}{\partial z^{(4)}}\cdot \frac{\partial z^{(4)}}{\partial z^{(3)}}\cdot \frac{\partial z^{(3)}}{\partial z^{(2)}}\cdot \frac{\partial z^{(2)}}{\partial \Theta _{ij}^{(1)}}

已知 \frac{\partial cost(I)}{\partial z^{(4)}}=\delta ^{(4)}\frac{\partial z^{(4)}}{\partial z^{(3)}}=\Theta ^{(3)}g^{'}(z^{(3)})\frac{\partial z^{(3)}}{\partial z^{(2)}}=\Theta ^{(2)}g^{'}(z^{(2)})

又由于

z_{1}^{(2)}=\Theta _{10}^{(1)}a_{0}^{(1)}+\Theta _{11}^{(1)}a_{1}^{(1)}+\Theta _{12}^{(1)}a_{2}^{(1)}

z_{2}^{(2)}=\Theta _{20}^{(1)}a_{0}^{(1)}+\Theta _{21}^{(1)}a_{1}^{(1)}+\Theta _{22}^{(1)}a_{2}^{(1)}

故有:

\frac{\partial z^{(2)}}{\partial \Theta _{ij}^{(1)}}=a_{j}^{(1)} 

因此,

 \frac{\partial cost(I)}{\partial \Theta _{ij}^{(1)}}=\delta ^{(4)}\cdot\Theta ^{(3)}g^{'}(z^{(3)})\cdot\Theta ^{(2)}g^{'}(z^{(2)})\cdot a_{j}^{(1)}

                                                   =\delta ^{(3)}\cdot \Theta ^{(2)}g^{'}(z^{(2)})\cdot a_{j}^{(1)}

                                                   =\delta ^{(2)}a_{j}^{(1)}

综上,有:

 \frac{\partial cost(I)}{\partial \Theta _{ij}^{(3)}}=\delta ^{(4)}a_{j}^{(3)}

\frac{\partial cost(I)}{\partial \Theta _{ij}^{(2)}}=\delta ^{(3)}a_{j}^{(2)}

\frac{\partial cost(I)}{\partial \Theta _{ij}^{(1)}}=\delta ^{(2)}a_{j}^{(1)}

因此,有:

\frac{\partial cost(I)}{\partial \Theta _{ij}^{(l)}}=\delta ^{(l+1)}a_{j}^{(l)}

四、基于前馈神经网络的手写体数字识别

首先查看手写体数据集情况:

from scipy.io import loadmat

data=loadmat("C:\\Users\\LEGION\\Documents\\Tencent Files\\215503595\\FileRecv\\hw11data.mat")
X=data['X']
y=data['y']
print('X type:',type(X))
print('X shape:',X.shape)
print('y type:',type(y))
print('y shape:',y.shape)
X type: <class 'numpy.ndarray'>
X shape: (5000, 400)
y type: <class 'numpy.ndarray'>
y shape: (5000, 1)

接着,从数据集中随机选取100行并转化成图片:

from random import sample
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

'''随机选取100行'''
r=[int(i) for i in range(5000)]
R=sample(r,100)
X_choose=np.zeros((100,400))
for i in range(100):
    X_choose[i,:]=X[R[i],:]
    
'''将随机选取的100行数据分别转换成20X20的矩阵形式'''
X_matrix=[X_choose[i].reshape([20,20]).T for i in range(100)]

'''转换成图片'''
fig=plt.figure()
for i in range(100):
    ax=fig.add_subplot(10,10,i+1)
    ax.imshow(X_matrix[i],interpolation='nearest')
plt.show()

查看已经训练好的权重数据集情况:

from scipy.io import loadmat

weights=loadmat("C:\\Users\\LEGION\\Documents\\Tencent Files\\215503595\\FileRecv\\hw11weights.mat")
theta1=weights['Theta1']
theta2=weights['Theta2']
print('theta1 tyep:',type(theta1))
print('theta1 shape:',theta1.shape)
print('theta2 type:',type(theta2))
print('tehta2 shape:',theta2.shape)
theta1 tyep: <class 'numpy.ndarray'>
theta1 shape: (25, 401)
theta2 type: <class 'numpy.ndarray'>
tehta2 shape: (10, 26)

计算前馈神经网络对手写体数字识别的准确率:

'''添加元素1'''
X0=X.tolist()
for i in range(5000):
    X0[i].insert(0,1)
X1=np.array(X0)

'''进行神经网络的第一层计算'''
Z1=[]   #5000 date of second layer
for i in range(5000):
    a=np.dot(theta1,X1[i].T)
    z1=(a.T).tolist()
    Z1.append(z1)

'''计算逻辑函数值'''
Y1=[]
for i in range(5000):
    y0=[]
    for j in range(25):
        b=1/(1+np.exp(-Z1[i][j]))
        y0.append(b)
    Y1.append(y0)


'''添加元素1'''
for i in range(5000):
    Y1[i].insert(0,1)
Y2=np.array(Y1)

'''进行神经网络的第二层计算'''
Z2=[]   #5000 date of third layer
for i in range(5000):
    a=np.dot(theta2,Y2[i].T)
    z2=(a.T).tolist()
    Z2.append(z2)
    
'''计算逻辑函数值'''
Y2=[]
for i in range(5000):
    y0=[]
    for j in range(10):
        c=1/(1+np.exp(-Z2[i][j]))
        y0.append(c)
    Y2.append(y0)
    
'''转换成输出值'''
Y=[]
for i in range(5000):
    s=Y2[i].index(max(Y2[i]))
    Y.append(s+1)
    
'''计算神经网络预测的准确率'''
n=0
for i in range(5000):
    if y[i]==Y[i]:
        n+=1
pre_ratio=n/5000
print("神经网络预测的准确率:{}".format(pre_ratio))
神经网络预测的准确率:0.9752

计算损失函数值:

from scipy.io import loadmat
import numpy as np


'''读取数据'''
data=loadmat("C:\\Users\\LEGION\\Documents\\Tencent Files\\215503595\\FileRecv\\hw11data.mat")
X=data['X']
y=data['y']

weights=loadmat("C:\\Users\\LEGION\\Documents\\Tencent Files\\215503595\\FileRecv\\hw11weights.mat")
theta1=weights['Theta1']
theta2=weights['Theta2']


#进行神经网络运算
'''添加元素1'''
X0=X.tolist()
for i in range(5000):
    X0[i].insert(0,1)
X1=np.array(X0)

'''进行神经网络的第一层计算'''
Z1=[]   #5000 date of second layer
for i in range(5000):
    a=np.dot(theta1,X1[i].T)
    z1=(a.T).tolist()
    Z1.append(z1)

'''计算逻辑函数值'''
Y1=[]
for i in range(5000):
    y0=[]
    for j in range(25):
        b=1/(1+np.exp(-Z1[i][j]))
        y0.append(b)
    Y1.append(y0)


'''添加元素1'''
for i in range(5000):
    Y1[i].insert(0,1)
Y2=np.array(Y1)

'''进行神经网络的第二层计算'''
Z2=[]   #5000 date of third layer
for i in range(5000):
    a=np.dot(theta2,Y2[i].T)
    z2=(a.T).tolist()
    Z2.append(z2)
    
'''计算逻辑函数值'''
Y2=[]
for i in range(5000):
    y0=[]
    for j in range(10):
        c=1/(1+np.exp(-Z2[i][j]))
        y0.append(c)
    Y2.append(y0)
    
'''转换成输出值'''
Y=[]
for i in range(5000):
    s=Y2[i].index(max(Y2[i]))
    Y.append(s+1)
    
#计算损失函数值
cost=0
for i in range(5000):
    cost0=0
    d=[0 for i in range(10)]
    d[y[i][0]-1]=1
    for j in range(10):
        p=d[j]*np.log(Y2[i][j])+(1-d[j])*np.log(1-Y2[i][j])
        cost0=cost0+p
    cost=cost+cost0
cost=cost*(-1/5000)
print("损失函数值:{}".format(cost))
损失函数值:0.2876291651613188

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

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

相关文章

消息队列使用指南

介绍 消息队列是一种常用的应用程序间通信方法&#xff0c;可以用来在不同应用程序或组件之间传递数据或消息。消息队列就像一个缓冲区&#xff0c;接收来自发送方的消息&#xff0c;并存储在队列中&#xff0c;等待接收方从队列中取出并处理。 在分布式系统中&#xff0c;消…

对无向图进行邻接矩阵的转化,并且利用DFS(深度优先)和BFS(广度优先)算法进行遍历输出, 在邻接矩阵存储结构上,完成最小生成树的操作。

一 实验目的 1&#xff0e;掌握图的相关概念。 2&#xff0e;掌握用邻接矩阵和邻接表的方法描述图的存储结构。 3&#xff0e;掌握图的深度优先搜索和广度优先搜索遍历的方法及其计算机的实现。 4&#xff0e;理解最小生成树的有关算法 二 实验内容及要求 实验内容&#…

【Angular开发】Angular在2023年之前不是很好

做一个简单介绍&#xff0c;年近48 &#xff0c;有20多年IT工作经历&#xff0c;目前在一家500强做企业架构&#xff0e;因为工作需要&#xff0c;另外也因为兴趣涉猎比较广&#xff0c;为了自己学习建立了三个博客&#xff0c;分别是【全球IT瞭望】&#xff0c;【架构师酒馆】…

第 119 场 LeetCode 双周赛题解

A 找到两个数组中的公共元素 模拟 class Solution { public:vector<int> findIntersectionValues(vector<int> &nums1, vector<int> &nums2) {unordered_set<int> s1(nums1.begin(), nums1.end()), s2(nums2.begin(), nums2.end());vector<…

C语言进阶之路-数据结构篇

目录 一、学习目标 二、数据结构 1.基本概念 线性关系&#xff1a; 非线性关系&#xff1a; 存储形式 2. 算法分析 2.1 时间复杂度 2.2 空间复杂度 2.3 时空复杂度互换 总结 一、学习目标 了解数据结构的基本概念了解算法的分析方法 二、数据结构 1.基本概念 数据结…

Si24R03—低功耗 SOC 芯片(集成RISC-V内核+2.4GHz无线收发器)

Si24R03是一款高度集成的低功耗SOC芯片&#xff0c;其集成了基于RISC-V核的低功耗MCU和工作在2.4GHz ISM频段的无线收发器模块。 MCU模块具有低功耗、Low Pin Count、宽电压工作范围&#xff0c;集成了13/14/15/16位精度的ADC、LVD、UART、SPI、I2C、TIMER、WUP、IWDG、RTC等丰…

hdlbits系列verilog解答(mt2015_q4)-54

文章目录 一、问题描述二、verilog源码三、仿真结果一、问题描述 本次使用系列文章52和53中实现的子模块,实现以下组合逻辑电路。 二、verilog源码 module top_module (input x, input y, output z);wire [3:0

EPICS modbus 模块数字量读写练习

本文使用modbus slave软件模拟一个受控的modbus设备&#xff0c;此模拟设备提供如下功能&#xff1a; 1、线圈组1&#xff0c;8个线圈&#xff0c;起始地址为0&#xff0c;数量为8&#xff0c;软件设置如下(功能码1)&#xff0c;用于测试功能码5&#xff0c;一次写一个线圈&am…

了解红帽认证

红帽公司成立于1993年&#xff0c;是全球首家收入超10亿美元的开源公司&#xff0c;总部位于美国&#xff0c;分支机构遍布全球。红帽公司作为全球领先的开源和Linux系统提供商&#xff0c;其产品已被业界广泛认可并使用&#xff0c;尤其是RHEL系统在业内拥有超高的Linux系统市…

利用Node.js和cpolar实现远程访问,无需公网IP和路由器设置的完美解决方案

文章目录 前言1.安装Node.js环境2.创建node.js服务3. 访问node.js 服务4.内网穿透4.1 安装配置cpolar内网穿透4.2 创建隧道映射本地端口 5.固定公网地址 前言 Node.js 是能够在服务器端运行 JavaScript 的开放源代码、跨平台运行环境。Node.js 由 OpenJS Foundation&#xff0…

Dockerfile的介绍和使用

什么是dockerfile? Dockerfile是一个包含用于组合映像的命令的文本文档。可以使用在命令行中调用任何命令。 Docker通过读取Dockerfile中的指令自动生成映像。 docker build命令用于从Dockerfile构建映像。可以在docker build命令中使用-f标志指向文件系统中任何位置的Dockerf…

c语言:理解和避免野指针

野指针的定义&#xff1a; 野指针是指一个指针变量存储了一个无效的地址&#xff0c;通常是一个未初始化的指针或者指向已经被释放的内存地址。当程序尝试使用野指针时&#xff0c;可能会导致程序崩溃、内存泄漏或者其他不可预测的行为。因此&#xff0c;在编程中需要特别注意…

二叉树前中后序遍历——(非)递归写法

文章目录 前言递归实现非递归实现力扣习题 红色&#xff1a;前序遍历顺序绿色&#xff1a;中序遍历顺序蓝色&#xff1a;后续遍历顺序 前言 二叉树遍历也分为两种 广度优先遍历&#xff08;Breadth-first order&#xff09;&#xff1a;尽可能先访问距离根最近的节点&#x…

未成年人保护成为《蛋仔派对》最高优先级工作,与家长携手保护孩子健康成长

《蛋仔派对》于近日发布致家长的第二封信&#xff0c;信中向社会各界公布了正在推出的三大“防沉迷”举措&#xff0c;严防“冒用成年人账号”等行为&#xff0c;针对家长关心的未成年防沉迷、冒用成年人账号、渠道服充值退款难等问题进行回应。 《蛋仔派对》表示始终把未成年…

多窗口文件管理工具Q-Dir安装以及使用教程

软件介绍 Q-Dir 是一款功能强大的Windows资源管理器&#xff0c;可以非常方便的管理你的各种文件。Q-Dir有4 个窗口&#xff0c;特别适用于频繁在各个目录间跳跃复制粘贴的情况&#xff0c;每个窗口都可以方便的切换目录&#xff0c;以不同颜色区分不同类型的文件&#xff0c;…

分销电商结算设计

概述 分销电商中涉及支付与结算&#xff1b;支付职责是收钱&#xff0c;结算则是出钱给各利益方&#xff1b; 结算核心围绕业务模式涉及哪些费用&#xff0c;以及这些费用什么时候通过什么出资渠道&#xff0c;由谁给到收方利益方&#xff1b; 结算要素组成费用项结算周期出…

持续集成交付CICD:Jenkins配置Nexus制品上传流水线

目录 一、实验 1.Jenkins配置制品上传流水线 二、问题 1.上传制品显示名称有误 一、实验 1.Jenkins配置制品上传流水线 (1) 新建流水线项目 &#xff08;2&#xff09;描述 &#xff08;3&#xff09;添加参数 &#xff08;4&#xff09;查看构建首页 &#xff08;5&…

体验一下使用 ArkUI 进行 HarmonyOS 开发并与 Compose 简单对比

前言 最近几年各个技术公众号和技术群都在唱衰原生安卓开发&#xff0c;疯狂贩卖焦虑。 搞得我也焦虑的不行&#xff0c;在谷歌的 Compose 推出后就赶紧去学&#xff0c;但是又觉得好像 Compose 的热度也不算太高&#xff0c;又去学 Flutter 。 转头两个都还没学明白呢&…

机器学习入门笔记

文章目录 背景具体步骤1.环境搭建2.写个demo1.数据处理2.分割数据集3.用模型训练数据&#xff0c;并得到预测结果4.绘制结果5.评估 背景 最近学习了一些关于机器学习的内容&#xff0c;做个笔记。 具体步骤 1.环境搭建 需要用到的工具&#xff1a;pycharm&#xff0c;anaco…

YOLOv5目标检测

文章目录 软硬件环境前言安装GPU环境安装pytorch的GPU版本YOLOv5测试v3.0版本参考资料 软硬件环境 ubuntu 18.04 64bitanaconda with 3.7nvidia gtx 1070Ticuda 10.1pytorch 1.5YOLOv5 前言 YOLOv4还没有退热&#xff0c;YOLOv5就已经来了&#xff01; 6月9日&#xff0c…