全连接神经网络(Fully Connected Neural Network,简称FCNN)是一种基础的人工神经网络结构,也称为多层感知器(Multilayer Perceptron,MLP)。在这种神经网络中,每个神经元都与前一层和后一层的所有神经元相连接,形成一个密集的连接结构。这种网络结构主要由输入层、隐藏层和输出层构成,其中输入层负责接收原始数据,隐藏层和输出层神经元对信号进行加工处理,最终结果由输出层神经元输出。
全连接神经网络能够学习输入数据的复杂特征,并进行分类、回归等任务。这是因为全连接神经网络通过反向传播算法和梯度下降求解法,不断地调整网络参数,以减小网络输出与真实值之间的损失(Loss),从而实现对输入数据的准确分类或回归。全连接神经网络是许多其他复杂神经网络的基础,如卷积神经网络(CNN)、循环神经网络(RNN)和长短时记忆网络(LSTM)等。这些网络在全连接神经网络的基础上,引入了卷积、循环等更复杂的连接方式,以适应不同的任务和数据类型。在之前的文章中:神经网络1-基础过关-CSDN博客中,我们详细介绍过多层感知机的原理和机制。在这篇文章中,我们将进行一些基于python的代码示例,以帮助大学学习。
1. 全连接神经网络示例
我将使用TensorFlow和Keras API来构建和训练一个全连接神经网络,用于解决一个简单的二分类问题。首先,请确保您已经安装了TensorFlow。如果没有,你可以使用pip来安装:
pip install tensorflow
TensorFlow是由谷歌人工智能团队谷歌大脑开发和维护的深度学习平台,是目前人工智能领域主流的开发平台,具有广泛的应用用户群体。其命名来源于本身的运行原理,即Tensor(张量)意味着N维数组,Flow(流)意味着基于数据流图的计算,TensorFlow为张量从流图的一端流动到另一端计算过程。TensorFlow是将复杂的数据结构传输至人工智能神经网网中进行分析和处理过程的系统。
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from tensorflow.keras.utils import to_categorical
from sklearn.model_selection import train_test_split
from sklearn.datasets import make_classification
# 生成模拟的二分类数据集
X, y = make_classification(n_samples=1000, n_features=20, n_informative=2, n_redundant=10, random_state=42)
y = to_categorical(y)
# 划分数据集为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 构建全连接神经网络模型
model = Sequential()
model.add(Dense(64, activation='relu', input_shape=(20,))) # 输入层,20个特征,64个神经元,使用ReLU激活函数
model.add(Dense(64, activation='relu')) # 隐藏层,64个神经元,使用ReLU激活函数
model.add(Dense(2, activation='softmax')) # 输出层,2个神经元(对应二分类),使用softmax激活函数
# 编译模型,设置优化器、损失函数和评价指标
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
# 训练模型
model.fit(X_train, y_train, epochs=50, batch_size=32, validation_data=(X_test, y_test))
# 评估模型
loss, accuracy = model.evaluate(X_test, y_test)
print(f'Test Loss: {loss}, Test Accuracy: {accuracy}')
# 使用模型进行预测
predictions = model.predict(X_test)
print(predictions)
这个例子使用了Keras的高级API来构建一个具有一个输入层、一个隐藏层和一个输出层的简单全连接神经网络。模型用于对模拟生成的二分类数据集进行分类。我们使用make_classification
函数从sklearn.datasets
生成了一个包含1000个样本和20个特征的数据集,其中只有2个特征是有信息的,其余10个特征是冗余的。
在模型构建过程中,我们使用了Sequential
类来顺序地添加层。每一层都使用Dense
类来创建,它表示一个全连接的神经网络层。input_shape
参数指定了输入数据的形状。我们使用了ReLU作为隐藏层的激活函数,这是神经网络中常用的非线性激活函数。对于输出层,我们使用了softmax激活函数,因为我们处理的是一个二分类问题。
在模型编译时,我们使用了Adam优化器和分类交叉熵作为损失函数,这是二分类问题中常用的选择。我们还指定了准确率作为评价指标,以便在训练过程中监控模型的性能。然后,我们使用fit
方法来训练模型,指定了训练数据的批次大小和训练的轮数(epochs)。我们还提供了测试数据用于验证模型的性能。最后,我们使用evaluate
方法来评估模型在测试集上的性能,并打印出损失和准确率。我们还使用predict
方法来对测试集进行预测,并打印出预测结果。
为了增强示例的友好性,我们对每一个使用到的模块都进行了细致描述。下面是我们在上面示例中使用到的相关模块的具体解释。
2. sklearn.datasets.make_classification
sklearn.datasets.make_classification
是 Scikit-learn 库中用于生成随机分类数据集的一个非常有用的函数。该函数可以生成一个用于二分类或多分类问题的数据集,其中你可以控制数据集的许多属性,如样本数量、特征数量、信息性特征的数量、冗余特征的数量、噪声级别等。
以下是 make_classification
函数的一些关键参数:
n_samples
:生成的样本数。n_features
:每个样本的特征数。n_informative
:信息性特征的数量(即与分类结果相关的特征)。n_redundant
:冗余特征的数量(即与信息性特征相关但不直接与分类结果相关的特征)。n_repeated
:重复特征的数量(即完全复制信息性特征的数量)。n_classes
:类别数量(默认为2,即二分类)。n_clusters_per_class
:每个类别中的簇数量(仅当n_classes
> 2 时有效)。weights
:类别权重。flip_y
:随机反转标签的比例(即噪声)。random_state
:随机数生成器的种子或RandomState
实例。
10.2 tensorflow.keras.utils.to_categorical
tensorflow.keras.utils.to_categorical
是 TensorFlow 中 Keras API 的一个实用函数,用于将整数标签(通常是 0 到 n-1 的整数)转换为独热编码(one-hot encoding)格式。独热编码常用于神经网络模型的输出层,特别是分类任务中。
使用 to_categorical
函数时,你需要提供两个参数:
y
:整数标签的数组或列表。num_classes
:类别的数量。这通常是整数标签中的最大值加 1。
函数将返回一个二维数组,其中每个样本的标签都被转换为一个独热编码向量。对于每个样本,其真实类别的索引位置为 1,其余位置为 0。
下面是一个使用 to_categorical
的例子:
import tensorflow as tf
# 假设我们有 4 个样本,属于 3 个类别
labels = [0, 1, 2, 1]
# 使用 to_categorical 转换为独热编码
categorical_labels = tf.keras.utils.to_categorical(labels, num_classes=3)
print(categorical_labels.numpy())
[[1. 0. 0.]
[0. 1. 0.]
[0. 0. 1.]
[0. 1. 0.]]
在这个例子中,我们有 3 个类别(索引从 0 到 2),所以每个样本的标签都被转换为一个长度为 3 的向量。例如,第一个样本属于第 0 个类别,因此其独热编码为 [1, 0, 0]
;第二个和第四个样本属于第 1 个类别,因此它们的独热编码为 [0, 1, 0]
;第三个样本属于第 2 个类别,其独热编码为 [0, 0, 1]
。
10.3 sklearn.model_selection.train_test_split
sklearn.model_selection.train_test_split
是 scikit-learn 库中的一个函数,用于将数据集分割成训练集和测试集。在机器学习和数据科学中,这通常是一个重要的步骤,因为它允许你评估模型在未见过的数据上的性能。
这个函数的基本用法如下:
from sklearn.model_selection import train_test_split
# 假设 X 是特征数据,y 是标签数据
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
参数解释:
X, y
:分别表示特征数据和标签数据。test_size
:表示测试集所占的比例,例如test_size=0.2
表示测试集占整个数据集的 20%。random_state
:随机种子,用于确保每次分割数据时都能得到相同的结果,以便于实验的可重复性。
train_test_split
函数会随机地分割数据集,返回四个数组:
X_train
:用于训练的特征数据子集。X_test
:用于测试的特征数据子集。y_train
:与X_train
对应的标签数据子集。y_test
:与X_test
对应的标签数据子集。
除了上述参数外,该函数还包括一下几个参数:
- train_size:这也是一个介于0到1之间的浮点数或者一个整数,表示训练集应该包含的数据的比例或样本数量。如果同时指定了
test_size
和train_size
,则train_size
将优先使用。 -
shuffle:这是一个布尔值,默认为
True
。如果设置为True
,则数据将在分割之前被打乱,确保每次分割的结果都是随机的。如果为False
,则数据保持原始顺序进行分割。 -
stratify:这个参数通常用于分类问题,其中
y
是分类变量。如果指定了stratify=y
,则train_test_split
会尝试保持每个类别在训练集和测试集中的比例与原始数据集中的比例相同。这对于不平衡的数据集特别有用,因为它确保模型在训练时能够接触到所有类别的样本。
通过这样做,你可以使用 X_train
和 y_train
来训练你的模型,然后使用 X_test
和 y_test
来评估模型的性能。这个函数是 scikit-learn 中非常常用的一个函数,对于机器学习项目的实验设计和评估至关重要。
10.4 tensorflow.keras.layers.Dense
tensorflow.keras.layers.Dense
是 TensorFlow 中 Keras API 的一个核心层,用于添加全连接(或密集)层到神经网络模型中。全连接层通常用于神经网络的输入层、隐藏层和输出层。
Dense
层的主要参数包括:
-
units:正整数,定义了输出空间的维度,即该层中神经元(或节点)的数量。
-
activation:定义要使用的激活函数。如果不指定,则不使用激活函数(即线性激活:
a(x) = x
)。常见的激活函数包括'relu'
、'sigmoid'
、'tanh'
等。 -
use_bias:布尔值,指定该层是否使用偏置项。默认值是
True
。 -
kernel_initializer:权重矩阵的初始值设定项。默认是
'glorot_uniform'
,也可以使用其他初始化方法,如'he_normal'
、'zeros'
等。 -
bias_initializer:偏差向量的初始值设定项。默认是
'zeros'
。 -
kernel_regularizer:应用于权重矩阵的正则化函数,例如权重衰减。
-
bias_regularizer:应用于偏差向量的正则化函数。
-
activity_regularizer:应用于层输出(即激活)的正则化函数。
-
kernel_constraint:应用于权重矩阵的约束函数。
-
bias_constraint:应用于偏差向量的约束函数。
-
**kwargs:其他关键字参数,用于传递层特定的参数。
在 Keras 模型中,你可以通过以下方式添加一个 Dense
层:
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
model = Sequential()
model.add(Dense(units=64, activation='relu'))
在这个例子中,我们添加了一个具有 64 个神经元和 ReLU 激活函数的全连接层到序贯模型 model
中。Dense
层是全连接神经网络的核心组件,负责学习输入数据到输出数据之间的映射关系。通过调整权重和偏差,该层可以学习复杂的非线性模式。
10.5 tensorflow.keras.models.Sequential
tensorflow.keras.models.Sequential
是 TensorFlow 中 Keras API 提供的一个线性堆叠模型,用于简化神经网络模型的构建过程。Sequential
模型允许你将多个网络层线性地堆叠在一起,从而构建出神经网络模型。使用 Sequential
模型时,你只需要通过 add
方法将网络层逐个添加到模型中,然后编译模型、训练模型以及评估模型。这种方法非常适合快速原型设计和简单的神经网络结构。
下面是一个使用 Sequential
模型构建简单全连接神经网络的例子:
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
# 创建一个 Sequential 模型
model = Sequential()
# 向模型中添加第一个全连接层,64 个神经元,使用 ReLU 激活函数
model.add(Dense(64, activation='relu', input_shape=(input_dim,)))
# 向模型中添加第二个全连接层,32 个神经元,使用 ReLU 激活函数
model.add(Dense(32, activation='relu'))
# 向模型中添加输出层,10 个神经元,使用 softmax 激活函数(适用于分类问题)
model.add(Dense(10, activation='softmax'))
# 编译模型,指定优化器、损失函数和评估指标
model.compile(optimizer='adam',
loss='categorical_crossentropy',
metrics=['accuracy'])
# 在这里,你可以使用 model.fit 来训练模型,使用 model.evaluate 来评估模型,等等。
在上面的例子中,input_dim
应该被替换为输入数据的特征数量。这个模型包含一个输入层、一个隐藏层和一个输出层。
需要注意的是,虽然 Sequential
模型对于简单的网络结构非常方便,但它不支持复杂的网络拓扑结构,如多输入模型、多输出模型、共享层的模型以及具有非线性拓扑结构的模型。对于这些复杂的网络结构,你应该使用函数式 API(Functional API)来构建模型。
10.6 model.compile()
model.compile()
是 TensorFlow 和 Keras 中用于配置模型学习过程的函数。该函数接受几个关键参数,这些参数定义了模型在训练期间将如何进行优化和评估。以下是 model.compile()
中常用的参数及其描述:
-
optimizer: 优化器决定了如何根据模型的误差来更新网络的权重。常见的优化器包括
'adam'
,'sgd'
,'rmsprop'
, 等等。 -
loss: 损失函数衡量模型预测与实际标签之间的差异。对于不同的任务,会有不同的损失函数。例如,对于分类问题,可以使用交叉熵损失(
'categorical_crossentropy'
或'sparse_categorical_crossentropy'
),对于回归问题,可以使用均方误差('mean_squared_error'
)。 -
metrics: 列表,包含用于评估模型性能的指标。在分类问题中,常用的指标是准确率(
'accuracy'
)。对于回归问题,可以是均方误差('mean_squared_error'
)或其他相关指标。 -
loss_weights: 当模型具有多个输出时,这个参数允许你为每个输出指定不同的损失函数权重。例如,对于一个具有两个输出的模型,你可以这样设置:loss_weights=[0.7,0.3]。
-
weighted_metrics: 类似于
metrics
,但是允许为每个输出指定不同的指标权重。 -
run_eagerly: 布尔值,指定是否应在 Eager Execution 模式下运行模型。在大多数情况下,你应该保持这个值为
False
,以利用 TensorFlow 的图执行模式。 -
experimental_run_tf_function: 布尔值,控制是否应使用
tf.function
装饰器包装模型。这通常应该保持为True
,除非你有特殊的需求。
下面是一个 model.compile()
的例子,该例子配置了一个模型以使用 Adam 优化器,分类交叉熵损失函数,并监控准确率:
model.compile(optimizer='adam',
loss='categorical_crossentropy',
metrics=['accuracy'])
在调用 model.compile()
之后,你可以使用 model.fit()
来训练模型,使用 model.evaluate()
来评估模型,或使用 model.predict()
来进行预测。
注意:
metrics
参数允许你指定在训练和测试期间要评估的额外指标列表。这些指标将与主要损失函数一起在每个epoch结束时计算并报告。metrics
参数可以接受以下类型的值:
-
字符串:预定义的内置指标名称。例如,对于分类问题,常见的内置指标包括
accuracy
(准确率),precision
(精确度),recall
(召回率)和auc
(曲线下面积)。对于回归问题,常见的内置指标包括mean_squared_error
(均方误差)和mean_absolute_error
(平均绝对误差)。 -
函数:自定义的评估函数。这些函数应该接收两个参数:
y_true
(真实标签)和y_pred
(模型预测),并返回一个标量值或一个标量值的列表。def custom_metric(y_true, y_pred): # 计算自定义指标 ... return custom_metric_value model.compile(optimizer='adam', loss='binary_crossentropy', metrics=[custom_metric])
你应该根据具体的任务类型(如分类、回归等)选择适当的指标。同时,对于自定义指标,你需要确保它们适用于你的任务,并且能够正确地评估模型的性能。
10.7 model.fit()
model.fit()
是 TensorFlow 和 Keras 中用于训练模型的函数。该函数有多个参数,以下是一些常见的参数及其描述:
-
x: 输入数据。这可以是 Numpy 数组、TensorFlow 张量,或者是数据生成器(generator)或
keras.utils.Sequence
实例。 -
y: 目标数据(标签)。其形状应与
x
的样本数相匹配。对于监督学习问题,你需要提供此参数。 -
batch_size: 整数,指定每次更新模型时使用的样本数。较大的批次可能导致更快的训练,但也可能导致内存不足。较小的批次可能需要更多的训练步骤,但可能会得到更好的泛化性能。
-
epochs: 整数,整个数据集将被训练的轮数。一个 epoch 意味着整个数据集已经被看过一次。
-
verbose: 日志显示模式。0 表示不在标准输出流输出日志信息,1 表示显示进度条记录。
-
validation_data: 形式为
(x_val, y_val)
的元组,用于在训练期间评估模型。x_val
和y_val
分别是验证集的输入和目标数据。 -
validation_split: 0 到 1 之间的浮点数,用于将训练数据分割为训练和验证数据。如果提供了
validation_data
,则此参数将被忽略。 -
shuffle: 布尔值,指示是否在每个 epoch 开始时随机打乱训练数据。
-
callbacks: 在训练过程中的不同点调用的回调函数列表。例如,你可以在每个 epoch 结束后保存模型,或者在验证损失不再改善时提前停止训练。
-
learning_rate: 学习率,用于控制模型权重更新的步长。这通常是一个较小的正数,如 0.001。
-
optimizer: 优化器对象,用于更新模型权重以最小化损失函数。常见的优化器包括 Adam、SGD、RMSprop 等。
-
loss: 损失函数,用于量化模型预测与实际标签之间的差异。常见的损失函数包括均方误差、交叉熵等。
-
metrics: 列表,包含用于评估模型性能的指标。例如,对于分类问题,你可能想要跟踪准确率。
以下是一个 model.fit()
的例子:
model.fit(x_train, y_train, batch_size=32, epochs=10, verbose=1,
validation_data=(x_val, y_val), shuffle=True)
注意:
callbacks
是 model.fit()
函数中的一个重要参数,它允许你在训练过程中的不同阶段执行特定的操作。callbacks
参数接受一个列表,其中可以包含多种类型的回调函数(callback objects)。这些回调函数会在训练的不同阶段被调用,例如在每个 epoch 开始时、结束时,或者在每个 batch 之后等。
使用 callbacks
可以实现多种功能,比如:
- 在每个 epoch 结束后保存模型权重。
- 在验证损失不再提高时提前停止训练。
- 在训练过程中显示进度条。
- 在训练结束后绘制损失和准确率的曲线图。
下面是一些常见的回调函数和如何在 model.fit()
中使用它们:
- ModelCheckpoint: 用于在每个 epoch 结束后保存模型权重。
from tensorflow.keras.callbacks import ModelCheckpoint checkpoint = ModelCheckpoint('my_model_weights.h5', monitor='val_loss', save_best_only=True) model.fit(x_train, y_train, epochs=10, validation_data=(x_val, y_val), callbacks=[checkpoint])
- EarlyStopping: 用于在验证损失不再提高时提前停止训练。
from tensorflow.keras.callbacks import EarlyStopping early_stopping = EarlyStopping(monitor='val_loss', patience=3) model.fit(x_train, y_train, epochs=10, validation_data=(x_val, y_val), callbacks=[early_stopping])
- TensorBoard: 用于将训练过程中的数据写入 TensorBoard,以便可视化。
from tensorflow.keras.callbacks import TensorBoard tensorboard = TensorBoard(log_dir='./logs') model.fit(x_train, y_train, epochs=10, validation_data=(x_val, y_val), callbacks=[tensorboard])
- LearningRateScheduler: 用于在训练过程中调整学习率。
from tensorflow.keras.callbacks import LearningRateScheduler def scheduler(epoch): if epoch < 10: return 0.01 else: return 0.001 lr_scheduler = LearningRateScheduler(scheduler) model.fit(x_train, y_train, epochs=20, validation_data=(x_val, y_val), callbacks=[lr_scheduler])
- ReduceLROnPlateau: 用于当学习停滞时减少学习率。
from tensorflow.keras.callbacks import ReduceLROnPlateau reduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.1, patience=3, verbose=1) model.fit(x_train, y_train, epochs=10, validation_data=(x_val, y_val), callbacks=[reduce_lr])
在 model.fit()
中使用 callbacks
参数时,只需将回调函数的实例列表传递给该参数即可。这些回调函数将在训练的不同阶段被自动调用,帮助你更好地控制和管理训练过程。
10.8 model.evaluate()
model.evaluate()
是 TensorFlow 和 Keras 中用于评估模型性能的函数。这个函数会返回模型在给定测试数据上的损失值(loss)和任何你指定的模型指标(metrics)。与 model.fit()
不同,model.evaluate()
不会更新模型的权重。
以下是 model.evaluate()
的一些关键参数:
-
x: 输入数据,用于评估模型。这可以是 Numpy 数组、TensorFlow 张量,或者是一个生成器。
-
y: 真实的目标数据(标签)。对于监督学习问题,你需要提供这个参数来与模型的预测进行比较。
-
batch_size: 一个整数,指定每次评估时使用的样本数。这有助于在内存有限的情况下评估大数据集。
-
verbose: 日志显示模式。通常设置为 0(不在标准输出流输出日志信息)或 1(显示进度条记录)。
-
sample_weight: 可选的权重数组,用于对模型输出的每个样本进行加权。这可以用于处理不平衡的数据集。
-
steps: 当输入数据是生成器时,指定从生成器中抽取的步数(批次数)用于评估。
-
max_queue_size, workers, use_multiprocessing: 这些参数仅当使用进程(而非线程)来执行数据预处理时才有用。它们控制数据预处理的并行程度。
下面是一个使用 model.evaluate()
的例子:
# 假设你已经训练了一个模型并保存为 `model`
loss, accuracy = model.evaluate(x_test, y_test, verbose=1)
print(f'Test loss: {loss}')
print(f'Test accuracy: {accuracy}')
在这个例子中,模型会在测试数据集 x_test
和 y_test
上进行评估,然后返回损失值和准确率。这些值可以用于衡量模型在未见过的数据上的性能。
请注意,model.evaluate()
返回的指标列表取决于你在模型编译时指定的指标。如果你没有指定任何额外的指标,那么 model.evaluate()
只会返回损失值。如果你添加了额外的指标,比如准确率,那么这些指标也会作为 model.evaluate()
的返回值返回。如果你使用了多个评估指标,那么 model.evaluate()
将返回一个包含所有指标值的列表。例如,如果你还指定了 AUC(Area Under the Curve)作为另一个评估指标,那么返回值可能会是:
loss, accuracy, auc = model.evaluate(x_test, y_test, batch_size=32, verbose=1)
这里 auc
是模型在测试数据上的 AUC 值。需要注意的是,返回的评估指标列表中的顺序和数量与你在模型编译时通过 metrics
参数指定的顺序和数量一致。如果你没有指定任何额外的评估指标,那么 model.evaluate()
将只返回损失值。
此外,model.evaluate()
的返回值并不包括模型本身或其权重,它只提供了对模型性能的评估结果。如果你希望保存模型的权重或结构,你需要使用其他方法,如 model.save_weights()
或 model.save()
。
10.9 model.predict()
model.predict()
是 TensorFlow 和 Keras 中用于进行模型预测的函数。当你训练了一个模型之后,你可以使用这个函数来对新的、未见过的数据进行预测。
函数的基本用法如下:
predictions = model.predict(x)
其中 x
是你要进行预测的数据,它应该是一个 NumPy 数组或者是一个与模型输入兼容的数据结构(如 TensorFlow 的 tf.data.Dataset
)。
model.predict()
的返回值 predictions
是一个 NumPy 数组,包含了模型对输入数据 x
的预测结果。预测结果的形状和类型取决于模型的输出层。
例如,对于一个分类问题,如果你的模型有一个带有 10 个输出节点的 softmax 层,那么 predictions
将是一个形状为 (num_samples, 10)
的二维数组,其中 num_samples
是输入数据 x
中的样本数量。数组的每一行都表示一个样本属于各个类别的概率。对于回归问题,输出可能是一个形状为 (num_samples,)
的一维数组,其中每个值都是模型对相应输入样本的预测值。
model.predict()
还可以接受一个 batch_size
参数来指定批处理大小,这对于处理大量数据时非常有用,因为它允许你分批次地进行预测,而不是一次性处理所有数据。
predictions = model.predict(x, batch_size=32)
在这个例子中,模型将分批次处理输入数据,每个批次包含 32 个样本。
最后,model.predict()
还可以接受其他参数,如 verbose
(用于控制日志输出的冗余程度)和 steps
(当使用 tf.data.Dataset
作为输入时,指定要运行的步数)。