引言
神经元、层和神经网络是深度学习模型的核心组成部分,它们共同工作,使得深度学习能够处理复杂的数据和任务。通过叠加多个层,可以构建出能够学习复杂函数的深度神经网络
一、神经元和层
深度学习中的神经元和层是构建复杂预测模型的基础组件。以下是关于它们的一些基本概念:
1.1 神经元(Neuron)
1.1.1 定义
神经元是深度学习模型的基本单元,它模拟人脑中的神经元。在数学上,神经元接收输入,通过权重和偏置进行转换,并应用一个激活函数来产生输出
1.1.2 功能
每个神经元执行以下操作:
- 加权求和:计算输入向量的加权和(输入值乘以对应的权重,然后求和)
- 添加偏置:将一个偏置项加到加权求和的结果上
- 激活函数:应用一个非线性函数(激活函数)到上述结果上,以产生神经元的输出
- 激活函数:常用的激活函数包括
Sigmoid
、ReLU
(Rectified Linear Unit)、Tanh
等。激活函数引入了非线性因素,使得神经网络能够学习和模拟复杂函数
1.2 层(Layer)
1.2.1 定义
层是由多个神经元组成的集合,它在神经网络中执行特定的变换
1.2.2 类型
- 输入层(Input Layer):接收外部数据输入的层
- 隐藏层(Hidden Layer):位于输入层和输出层之间的层,可以进行特征学习和表示转换
- 输出层(Output Layer):产生最终预测或分类结果的层
- 全连接层(Dense Layer):层中的每个神经元都与前一层的所有神经元相连
1.3 神经元和层的关系
- 在深度学习中,神经元通过层组织起来,形成神经网络(Neural Network)
- 每一层都是前一层的输出和后一层的输入,层与层之间通过权重(weights)和偏置(biases)连接
- 神经网络通过前向传播(Forward Propagation)来计算输出,通过反向传播(Back Propagation)来更新权重和偏置,从而学习数据中的模式
1.4 应用
- 在深度学习模型中,通过叠加多个层,可以构建出能够学习复杂函数的深度神经网络(Deep Neural Networks, DNN)
- 这种结构在图像识别、语音识别、自然语言处理等领域表现出色,能够处理大量的数据并提取出有用的特征
1.5 总结
神经元和层是深度学习模型的核心组成部分,它们共同工作,使得深度学习能够处理复杂的数据和任务
二、探索神经元/单元和层的内部工作原理
在这个实验中,我们将探索神经元/单元和层的内部工作原理。并且与已经学到的回归/线性模型和逻辑模型进行对比。实验将介绍Tensorflow
,并展示这些模型如何在那个框架中实现
2.1 包
2.1.1 Tensorflow和Keras
Tensorflow
是由谷歌开发的一个机器学习包。2019年,谷歌将Keras
集成到Tensorflow
中,并发布了Tensorflow 2.0
。Keras
是由François Chollet独立开发的框架,它为Tensorflow
提供了一个简单、以层为中心的接口
import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf
from tensorflow.keras.layers import Dense, Input
from tensorflow.keras import Sequential
from tensorflow.keras.losses import MeanSquaredError, BinaryCrossentropy
from tensorflow.keras.activations import sigmoid
from lab_utils_common import dlc
from lab_neurons_utils import plt_prob_1d, sigmoidnp, plt_linear, plt_logistic
plt.style.use('./deeplearning.mplstyle')
import logging
logging.getLogger("tensorflow").setLevel(logging.ERROR)
tf.autograph.set_verbosity(0)
2.2 无激活函数的神经元 - 回归/线性模型
2.2.1 数据集
我们将使用课程1中的一个例子,对房价进行线性回归
X_train = np.array([[1.0], [2.0]], dtype=np.float32) #(以1000平方英尺为单位的大小)
Y_train = np.array([[300.0], [500.0]], dtype=np.float32) #(以1000美元为单位的房价)
fig, ax = plt.subplots(1,1)
ax.scatter(X_train, Y_train, marker='x', c='r', label="Data Points")
ax.legend( fontsize='xx-large')
ax.set_ylabel('Price (in 1000s of dollars)', fontsize='xx-large')
ax.set_xlabel('Size (1000 sqft)', fontsize='xx-large')
plt.show()
输出结果:
2.2.3 回归/线性模型
由无激活函数的神经元实现的函数与课程1中的线性回归相同:
f
w
,
b
(
x
(
i
)
)
=
w
⋅
x
(
i
)
+
b
(
1
)
f_{w,b}(x(i)) = w \cdot x(i) + b \quad (1)
fw,b(x(i))=w⋅x(i)+b(1)
我们可以定义一个只有一个神经元或单元的层,并与熟悉的线性回归函数进行比较
linear_layer = tf.keras.layers.Dense(units=1, activation = 'linear', )
# 查看权重
linear_layer.get_weights()
输出结果:
还没有权重,因为权重还没有实例化。让我们尝试一下模型在X_train中的一个例子上。这将触发权重的实例化。注意,层的输入必须是2-D的,所以我们将其重塑。
a1 = linear_layer(X_train[0].reshape(1,1))
print(a1)
输出结果:
结果是形状为(1,1)的张量(数组的另一种名称),即一个条目
现在让我们看看权重和偏置。这些权重是随机初始化为小数,偏置默认初始化为零
w, b= linear_layer.get_weights()
print(f"w = {w}, b={b}")
输出结果:
具有单个输入特征的线性回归模型(1)将有一个权重和一个偏置。这与我们上面的linear_layer相匹配
权重是随机初始化的,所以让我们将它们设置为一个已知的值
set_w = np.array([[200]])
set_b = np.array([100])
# set_weights接受一个numpy数组列表
linear_layer.set_weights([set_w, set_b])
print(linear_layer.get_weights())
输出结果:
让我们比较方程(1)和层输出
a1 = linear_layer(X_train[0].reshape(1,1))
print(a1)
alin = np.dot(set_w,X_train[0].reshape(1,1)) + set_b
print(alin)
输出结果:
它们产生相同的值,我们可以使用我们的线性层来预测我们的训练数据
prediction_tf = linear_layer(X_train)
prediction_np = np.dot( X_train, set_w) + set_b
plt_linear(X_train, Y_train, prediction_tf, prediction_np)
输出结果:
2.3 带Sigmoid激活函数的神经元
由带Sigmoid
激活函数的神经元/单元实现的函数与课程1中的逻辑回归相同:
f
w
,
b
(
x
(
i
)
)
=
g
(
w
x
(
i
)
+
b
)
(
2
)
f_{w,b}(x(i)) = g(w x(i) + b) \quad (2)
fw,b(x(i))=g(wx(i)+b)(2)
其中
g
(
x
)
=
sigmoid
(
x
)
g(x) = \text{sigmoid}(x)
g(x)=sigmoid(x)
让我们将
w
w
w和
b
b
b设置为一个已知的值,并检查模型
2.3.1 数据集
我们将使用课程1中的一个例子,进行逻辑回归
X_train = np.array([0., 1, 2, 3, 4, 5], dtype=np.float32).reshape(-1,1) # 2-D矩阵
Y_train = np.array([0, 0, 0, 1, 1, 1], dtype=np.float32).reshape(-1,1) # 2-D矩阵
pos = Y_train == 1
neg = Y_train == 0
X_train[pos]
输出结果:
pos = Y_train == 1
neg = Y_train == 0
fig,ax = plt.subplots(1,1,figsize=(4,3))
ax.scatter(X_train[pos], Y_train[pos], marker='x', s=80, c = 'red', label="y=1")
ax.scatter(X_train[neg], Y_train[neg], marker='o', s=100, label="y=0", facecolors='none',
edgecolors=dlc["dlblue"],lw=3)
ax.set_ylim(-0.08,1.1)
ax.set_ylabel('y', fontsize=12)
ax.set_xlabel('x', fontsize=12)
ax.set_title('单变量图')
ax.legend(fontsize=12)
plt.show()
输出结果:
2.3.2 逻辑神经元
我们可以通过添加Sigmoid
激活函数来实现一个’逻辑神经元’。然后,神经元的函数由上面的(2)式描述。
这一部分将创建一个包含我们的逻辑层的Tensorflow
模型,以展示创建模型的一种替代方法。Tensorflow
通常用于创建多层模型。Sequential模型是构建这些模型的一个方便方式。
model = Sequential(
[
tf.keras.layers.Dense(1, input_dim=1, activation = 'sigmoid', name='L1')
]
)
model.summary()
输出结果:
model.summary()显示了模型的层和参数数量。这个模型中只有一个层,而且这个层只有一个单元。这个单元有两个参数,𝑤和𝑏
logistic_layer = model.get_layer('L1')
w,b = logistic_layer.get_weights()
print(w,b)
print(w.shape,b.shape)
输出结果:
让我们将权重和偏置设置为一个已知的值
set_w = np.array([[2]])
set_b = np.array([-4.5])
# set_weights接受一个numpy数组列表
logistic_layer.set_weights([set_w, set_b])
print(logistic_layer.get_weights())
输出结果:
让我们比较方程(2)和层输出。
a1 = model.predict(X_train[0].reshape(1,1))
print(a1)
alog = sigmoidnp(np.dot(set_w,X_train[0].reshape(1,1)) + set_b)
print(alog)
输出结果:
它们产生相同的值,可以使用我们的逻辑层和
NumPy
模型来预测我们的训练数据
plt_logistic(X_train, Y_train, model, set_w, set_b, pos, neg)
输出结果:
上面的阴影反映了
Sigmoid
的输出,其值在0到1之间变化
2.4 总结
- 已构建了一个非常简单的神经网络
- 已经探索神经元与线性回归和逻辑回归的相似之处