深度学习基础知识2-线性神经网络
概述
在神经网络中,线性神经网络(Linear Neural Network)通常指的是只包含线性变换(线性映射)的神经网络层,也被称为全连接层(Fully Connected Layer)或密集层(Dense Layer)。
一个典型的线性神经网络层可以表示为:
[ y = W \cdot x + b ]
其中:
- (y) 是输出向量。
- (W) 是权重矩阵。
- (x) 是输入向量。
- (b) 是偏置向量。
这是一个线性变换,(W \cdot x) 表示输入 (x) 与权重矩阵 (W) 的矩阵乘法,然后加上偏置 (b)。这个线性变换是神经网络中最简单的一种。
训练过程:
在训练线性神经网络时,通常使用梯度下降或其变体进行优化。损失函数(Loss Function)用于度量模型的输出与实际标签之间的差异。通过反向传播算法,计算损失相对于权重和偏置的梯度,并使用梯度下降法来更新权重和偏置,以最小化损失函数。
应用:
线性神经网络广泛应用于各种机器学习任务,包括回归问题和分类问题。然而,由于它们只进行线性变换,无法捕捉数据中的非线性关系。因此,对于复杂的非线性任务,通常需要引入非线性激活函数或者使用更深层次的神经网络结构。
在深度学习中,线性神经网络通常被视为神经网络中的基本组件,被堆叠或组合以构建更复杂的网络结构。
线性神经网络与单层感知器的关系
线性神经网络与单层感知器之间存在紧密的关系,事实上,单层感知器可以被视为一种特殊形式的线性神经网络。为了理解它们的关系,让我们先回顾一下单层感知器的定义:
单层感知器(Single-Layer Perceptron):
单层感知器是一种最简单的神经网络形式,它包含一个输入层和一个输出层,没有任何隐藏层。输出层中的每个神经元都与输入层中的每个神经元相连接,并且每个连接都有一个权重。输出是通过对输入和权重进行加权和(线性组合)然后通过激活函数处理得到的。
数学表示为:
[ y = f(\sum_i w_i \cdot x_i + b) ]
其中:
- (y) 是输出。
- (f) 是激活函数。
- (w_i) 是权重。
- (x_i) 是输入。
- (b) 是偏置。
线性神经网络:
线性神经网络是一个更一般的概念,它可以包含多个层,每一层都进行线性变换。当我们将层数限制为一层时,线性神经网络就等同于单层感知器。在这种情况下,激活函数通常是恒等函数,即 (f(x) = x)。
所以,单层感知器是线性神经网络的一个特例,其特点是只有一层,且激活函数为恒等函数。当我们在单层感知器中引入非线性激活函数时,它就演变成了通常所说的多层感知器(MLP),这时可以通过增加隐藏层来学习更复杂的非线性关系。
理解为学习的数学方程式
import numpy as np
import matplotlib.pyplot as plt
#定义输入数据
X=np.array([[1,3,3],[1,4,3],[1,1,1],[1,2,1]])
#定义标签
T = np.array([[1],[1],[-1],[-1]])
#权值初始化
W = np.random.random([3,1])
#设置学习率
lr = 0.1
#神经网络输出
Y=0
#更新权值函数
def train():
global X,Y,T,lr,W
#同时计算4个数据的预测值,Y(4,1)
Y = np.dot(X,W)
#T-Y得到4个标签值与预测值的误差E(4,1)
E = T-Y
#计算权值的变化
delta_W = lr*(X.T.dot(E))/X.shape[0]
#更新权值
W = W+delta_W
#训练模型
for i in range(100):
#更新权值
train()
#画图
#正样本的XY坐标
x1 = [3,4]
y1 = [3,3]
#负样本xy坐标
x2 = [1,2]
y2 = [1,1]
#斜率与截距
k = -W[1]/W[2]
b = -W[0]/W[2]
#设定两个点
xdata =(0,5)
#通过两点来确定一条直线,用红色的线画出分界线
plt.plot(xdata,xdata*k+b,'r')
# 用蓝色的点画正样本
plt.scatter(x1,y1,c='b')
# 用黄色的点画负样本
plt.scatter(x2,y2,c='y')
plt.title("loop :%d"%i)
plt.waitforbuttonpress()
plt.close()
这段代码实现了一个简单的感知器模型的训练和可视化。下面是对代码的逐行解释:
- 导入 NumPy 和 Matplotlib 库。
- 定义输入数据
X
,其中每一行代表一个样本,第一列为1,表示偏置项。 - 定义标签
T
,表示每个样本的类别。 - 初始化权值
W
,使用np.random.random([3,1])
随机生成包含偏置项在内的权值。 - 设置学习率
lr
为 0.1。 - 定义神经网络输出
Y
为 0,这是为了在训练之前进行初始化。 - 定义更新权值的函数
train()
,其中计算预测值Y
,计算误差E
,并更新权值W
。 - 使用循环进行模型训练,每次迭代都调用
train()
更新权值。 - 在每次迭代中,画图来可视化训练过程:
- 定义正样本的坐标
x1
、y1
和负样本的坐标x2
、y2
。 - 计算分界线的斜率
k
和截距b
。 - 画出分界线和正负样本点,并显示迭代次数。
- 使用
plt.waitforbuttonpress()
使图像等待按键后关闭,从而实现动态可视化。
- 定义正样本的坐标
这个示例中使用了简单的二维数据和一个二分类任务,通过训练感知器模型来找到分界线,将正负样本分开。模型通过不断迭代更新权值,最终得到能够正确分类的分界线。
在 NumPy 库中,shape
是一个返回数组的维度的元组的属性。它表示数组的大小,即每个维度上的元素数量。对于二维数组,shape
返回一个包含两个元素的元组,第一个元素是行数,第二个元素是列数。
例如:
import numpy as np
arr = np.array([[1, 2, 3], [4, 5, 6]])
print(arr.shape)
输出:
(2, 3)
这表示 arr
是一个包含 2 行 3 列的二维数组。shape
属性对于理解数组的结构和在进行各种操作时确保维度一致性非常有用。
线性神经网络异或问题
线性神经网络(Perceptron)是一个单层的神经网络,它在解决异或(XOR)问题上存在局限性。异或问题是一个二分类问题,输入包含两个特征(0或1),输出是这两个特征的异或运算结果。具体来说,当输入的两个特征相同时输出为0,当输入的两个特征不同时输出为1。
由于线性神经网络的输出是输入的线性组合通过阈值函数(例如阶跃函数)的结果,它只能够表示线性可分的问题。而异或问题是线性不可分的,因此线性神经网络无法解决这个问题。
解决异或问题的一种方法是使用多层感知器(Multilayer Perceptron,MLP)或者更深层的神经网络。通过引入非线性激活函数,多层感知器可以学习更复杂的特征表示,从而能够处理线性不可分的问题。
以下是使用Python和NumPy库实现的一个简单的多层感知器解决异或问题的例子:
import numpy as np
# 定义激活函数(sigmoid)
def sigmoid(x):
return 1 / (1 + np.exp(-x))
# 定义导数(sigmoid的导数)
def sigmoid_derivative(x):
return x * (1 - x)
# 输入数据
X = np.array([[0, 0],
[0, 1],
[1, 0],
[1, 1]])
# 输出标签
y = np.array([[0],
[1],
[1],
[0]])
# 初始化权重和偏置
input_size = 2
hidden_size = 4
output_size = 1
weights_input_hidden = np.random.uniform(size=(input_size, hidden_size))
weights_hidden_output = np.random.uniform(size=(hidden_size, output_size))
# 学习率
learning_rate = 0.1
# 训练模型
for epoch in range(10000):
# 前向传播
hidden_layer_input = np.dot(X, weights_input_hidden)
hidden_layer_output = sigmoid(hidden_layer_input)
output_layer_input = np.dot(hidden_layer_output, weights_hidden_output)
predicted_output = sigmoid(output_layer_input)
# 计算误差
error = y - predicted_output
# 反向传播
output_delta = error * sigmoid_derivative(predicted_output)
hidden_error = output_delta.dot(weights_hidden_output.T)
hidden_delta = hidden_error * sigmoid_derivative(hidden_layer_output)
# 更新权重
weights_hidden_output += hidden_layer_output.T.dot(output_delta) * learning_rate
weights_input_hidden += X.T.dot(hidden_delta) * learning_rate
# 测试模型
test_input = np.array([[0, 0],
[0, 1],
[1, 0],
[1, 1]])
hidden_layer_input = np.dot(test_input, weights_input_hidden)
hidden_layer_output = sigmoid(hidden_layer_input)
output_layer_input = np.dot(hidden_layer_output, weights_hidden_output)
predicted_output = sigmoid(output_layer_input)
print("Predicted Output:")
print(predicted_output)
这个例子中使用了sigmoid作为激活函数,通过多层感知器的训练,模型能够学习到解决异或问题的表示。
而下面这个例子从反面说明线性神经网络无法解决异或问题
import numpy as np
import matplotlib.pyplot as plt
#输入数据
# 4个数据分别对应0与0异或,0与1异或,1与0异或,1与1异或
X = np.array([[1,0,0],[1,0,1],[1,1,0],[1,1,1]])
#标签,分别对应4种异或情况的结果
T = np.array([[-1],[1],[1],[-1]])
#权值初始化 。3行1列
W = np.random.random([3,1])
#学习率的设置
lr = 0.1
#神经网络的输出
Y = 0
#更新一次权值
def train():
#使用全局变量X,Y,W,lr
global X,Y,W,lr
#计算网络预测值
Y=np.dot(X,W)
#权值的变化计算
delta_W = lr*(X.T.dot(T-Y))/X.shape[0]
#更新权值
W = W+delta_W
for i in range(100):
#更新一次权值
train()
#-------画图部分-----------
#正样本
x1 = [0,1]
y1 = [1,0]
#负样本
x2 = [0,1]
y2 = [0,1]
#计算分界线的斜率以及截距
k = -W[1]/W[2]
d = -W[0]/W[2]
#设定两个点
xdata = (-2,3)
#通过两个点确定一条直线,用红色的线画出分界线
plt.plot(xdata,xdata*k+d,'red')
#用蓝色的点画出正样本
plt.scatter(x1,y1,c='b')
#黄色 负样本
plt.scatter(x2,y2,c='y')
#显示图
plt.show()
结果
这段代码是一个简单的使用感知器(Perceptron)解决异或(XOR)问题的示例。
-
输入数据(X):
- X是一个包含4个样本的矩阵,每个样本有3个特征。第一列是偏置项,始终为1,其余两列是输入特征。
-
标签(T):
- T是一个包含4个样本的列向量,对应于每个样本的标签。标签是1或-1,分别对应于两个类别。
-
权值初始化(W):
- W是一个包含3行1列的权重矩阵,其中每行对应一个输入特征,包括偏置项。这些权重是随机初始化的。
-
学习率(lr):
- lr是学习率,用于控制权值的更新步长。
-
神经网络输出(Y):
- Y是感知器的输出,计算为输入数据与权值的内积。
-
train
函数:train
函数用于更新权值,根据感知器的学习规则。它计算网络的预测值,然后根据误差更新权值。
-
循环训练(for循环):
- 在for循环中,权值通过多次迭代训练来逐步调整,以最终得到能正确分类异或问题的权值。
-
画图部分:
- 通过绘制正样本(类别1,蓝色点)和负样本(类别-1,黄色点),以及感知器确定的分界线(红色线),展示感知器的分类效果。
该代码演示了感知器在简单问题上的工作原理,但请注意,感知器只能解决线性可分问题。对于异或问题,感知器是无法收敛到正确解的,因为异或问题是线性不可分的。
delta学习规则
1986年,认知心理学家McClelland和Rumelhart 在神经网络训练中引入δ规则,该规则也可以称为连续感知器学习规则。
它是一种利用梯度下降法的一般性学习规则。
Delta学习规则通常用于神经网络的权重更新,特别是在使用梯度下降算法进行训练时。Delta规则的基本思想是根据网络输出与目标输出之间的误差,以及输入的导数来更新权重。
以下是Delta学习规则的基本步骤:
这个过程通常会反复进行,直到达到收敛条件为止。学习率 ( eta ) 的选择对训练的效果有影响,过大的学习率可能导致震荡,而过小的学习率可能导致收敛缓慢。 Delta规则是一种简单但有效的权重更新方法,特别适用于梯度下降法。
梯度下降
一维情况
二维: