- 🍨 本文为🔗365天深度学习训练营 中的学习记录博客
- 🍖 原作者:K同学啊
一、什么是RNN
RNN(Recurrent Neural Network)是一种特殊的神经网络,它能够处理序列数据,如时间序列、文本序列等。RNN与传统神经网络的主要区别在于其结构特点和计算机制。
- 结构特点:
- RNN由一系列相互连接的节点组成,每个节点代表一个状态。
- 这些节点通过反馈回路连接在一起,使得网络能够记住之前的状态信息。
- 计算机制:
- RNN在计算当前状态时,不仅考虑当前输入,还考虑上一个状态的信息。
- 这种机制使得RNN能够捕捉到数据的长期依赖性,适用于处理时间序列数据。
- 应用场景:
- RNN在自然语言处理领域有着广泛的应用,如机器翻译、文本生成等。
- 此外,RNN还可以用于预测时间序列数据,如股票价格、天气预测等。
- 局限性:
- RNN也存在一些局限性,例如对长序列的处理能力有限,以及可能出现的梯度消失问题。
- 改进方法:
- 为了解决这些问题,研究者提出了各种改进方法,如LSTM(Long Short-Term Memory)、GRU(Gated Recurrent Unit)等,它们在RNN的基础上增加了更多的结构和机制,以提高性能和稳定性。
二、前期准备
1.设置GPU
import tensorflow as tf
gpus = tf.config.list_physical_devices("GPU")
if gpus:
gpu0 = gpus[0]
tf.config.experimental.set_memory_growth(gpu0, True)
tf.config.set_visible_devices([gpu0], "GPU")
gpus
输出
[PhysicalDevice(name=‘/physical_device:GPU:0’, device_type=‘GPU’)]
2.导入数据
这里使用的是训练营提供心脏病数据。(这是数据各个标签对应的意思)
age: 1)年龄
sex: 2)性别
cp: 3)胸痛类型(4 values)
trestbps: 4)静息血压
chol: 5)血清胆固醇(mg/dl)
fbs: 6)空腹血糖>120 mg/dl
restecg: 7)静息心电图结果(值0,1,2)
thalach: 8)达到的最大心率
exang: 9)运动诱发的心绞痛
oldpeak: 10)相对于静止状态,运动引起的ST段压低
slope: 11)运动峰值ST段的斜率
ca: 12)荧光透视着色的主要血管数量(0-3)
thal: 13)0=正常;1=固定缺陷;2=可逆转的缺陷
target: 14)0=心脏病发作的几率较小1=心脏病发作的几率更大
import pandas as pd
import numpy as np
df = pd.read_csv("heart.csv")
df
输出
3.检查数据
df.isnull().sum()
是在Python的pandas库中用于数据清洗和预处理的一个函数组合,它的作用和用法如下:
作用:
df.isnull()
: 这个方法用于检测DataFrame中的缺失值,它会返回一个布尔型的DataFrame,其中每个单元格都会被判断是否为空(NaN),如果是空值,则对应的单元格为True
,否则为False
。.sum()
: 这个方法用于对DataFrame中的数据进行求和。当应用于布尔型DataFrame时,它会将True
视为1
,False
视为0
,然后对每一列进行求和,从而得到每列中True
(即缺失值)的总数。
用法:
df
: 这是你的DataFrame对象,通常是经过pandas读取数据后得到的。df.isnull()
: 调用这个方法后,会返回一个与原DataFrame形状相同的布尔型DataFrame,显示哪些元素是缺失值。df.isnull().sum()
: 在df.isnull()
的基础上调用.sum()
方法,会对每一列的缺失值进行计数,并返回一个Series对象,索引为原DataFrame的列名,值为对应列的缺失值数量。
示例:
假设有一个DataFrame df
如下:
import pandas as pd
import numpy as np
df = pd.DataFrame({
'A': [1, 2, np.nan],
'B': [4, np.nan, 6],
'C': [7, 8, 9]
})
# 使用 df.isnull().sum() 检查每列的缺失值数量
missing_values = df.isnull().sum()
print(missing_values)
输出将会是:
A 1
B 1
C 0
dtype: int64
这表示列’A’有一个缺失值,列’B’也有一个缺失值,而列’C’没有缺失值。通过这种方式,可以快速了解数据集中哪些列存在缺失值,以及缺失值的数量。
df.isnull().sum()
输出
age 0
sex 0
cp 0
trestbps 0
chol 0
fbs 0
restecg 0
thalach 0
exang 0
oldpeak 0
slope 0
ca 0
thal 0
target 0
dtype: int64
三、数据预处理
1.划分测试集与训练集
这一段代码的作用是进行数据预处理和分割,为机器学习模型的训练和测试做准备。
- 导入必要的库:
from sklearn.preprocessing import StandardScaler from sklearn.model_selection import train_test_split
StandardScaler
:这是scikit-learn库中的一个类,用于数据标准化。标准化是一个将数据转换为具有零均值和单位方差的过程。train_test_split
:这是scikit-learn库中的一个函数,用于将数据集分割成训练集和测试集。
- 数据分割:
X = df.iloc[:, :-1] y = df.iloc[:, -1]
df.iloc[:, :-1]
:这里使用pandas的.iloc
索引器来选择DataFramedf
的所有行和除了最后一列的所有列,这些被选中的列作为特征集(X)。df.iloc[:, -1]
:同样使用.iloc
索引器,这次选择DataFramedf
的所有行和最后一列,这一列通常是目标变量或标签(y)。
- 分割数据集:
x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0.1, random_state=1)
train_test_split(X, y, test_size=0.1, random_state=1)
:这个函数接受特征集和目标变量,并将它们分割成训练集和测试集。X
:特征集。y
:目标变量。test_size=0.1
:指定测试集的大小为原始数据集的10%。random_state=1
:设置随机数生成器的种子,以确保每次分割得到的数据集都是一样的,这对于可重复的实验是重要的。
综上所述,这段代码首先导入了用于数据预处理和分割的库,然后从DataFrame中提取了特征和目标变量,最后使用train_test_split
函数将数据分割成训练集和测试集,以便后续可以进行模型训练和评估。
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
X = df.iloc[:, :-1]
y = df.iloc[:, -1]
x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0.1, random_state=1)
x_train.shape,y_train.shape
输出
((272, 13), (272,))
2.标准化
这段代码的作用是对特征数据进行标准化处理,并将其重塑为适合输入到某些机器学习模型(特别是深度学习模型)的格式。
- 创建标准化器实例:
sc=StandardScaler()
StandardScaler()
:这是scikit-learn库中的一个类,用于标准化特征,通过去除均值(将数据中心的均值变为0)和缩放至单位方差(将数据的标准差变为1)来实现。这有助于使不同量级的特征具有相同的尺度,从而提高某些算法的收敛速度和性能。
- 标准化训练数据:
x_train=sc.fit_transform(x_train)
fit_transform(x_train)
:这是StandardScaler
类的一个方法,它执行两个操作:fit
:计算训练数据集的均值和标准差(即每个特征的均值和标准差),这些统计量将被用于后续的标准化过程。transform
:使用计算得到的均值和标准差对训练数据进行标准化处理。
- 标准化测试数据:
x_test=sc.transform(x_test)
transform(x_test)
:这是StandardScaler
类的一个方法,它使用在训练数据上计算得到的均值和标准差来对测试数据进行标准化。这样做可以保证训练集和测试集使用相同的标准化参数,从而避免数据泄露。
- 重塑数据形状:
x_train=x_train.reshape(x_train.shape[0],x_train.shape[1],1) x_test=x_test.reshape(x_test.shape[0],x_test.shape[1],1)
x_train.reshape(x_train.shape[0],x_train.shape[1],1)
和x_test.reshape(x_test.shape[0],x_test.shape[1],1)
:这些操作改变了数据的形状,使其具有三个维度。在很多深度学习模型中,特别是使用卷积神经网络(CNN)或循环神经网络(RNN)时,数据通常需要是三维的,其中三个维度分别代表样本数量、特征数量和时间步长(或通道数)。在这个例子中,第三个维度是1,表示每个样本只有一个时间步长(对于非序列数据)。
总的来说,这段代码首先对特征数据进行标准化处理,然后将数据重塑为三维格式,以便可以输入到需要这种数据格式的模型中。
四、构建RNN模型
tf.keras.layers.SimpleRNN
是 TensorFlow 中 Keras API 的一部分,用于创建一个简单的循环神经网络(RNN)层。以下是该函数的作用及其参数的解释:
作用:
SimpleRNN 层实现了一个基本的循环神经网络,它在每个时间步长跟踪更新“隐藏状态”,并根据当前的输入和前一个时间步长的隐藏状态来计算输出。这种层可以用于处理序列数据,因为它能够记住之前的信息,并将其用于当前的操作。
参数:
- units:整数,表示 RNN 层中的单元数(或神经元数)。这决定了输出空间的维度,即每个时间步长的输出向量的大小。
- activation:要使用的激活函数。默认为 ‘tanh’。其他常见的激活函数包括 ‘relu’ 和 ‘sigmoid’。激活函数决定了每个时间步长输出的非线性变换。
- use_bias:布尔值,表示是否在计算中添加偏置项(b)。默认为 True。如果设置为 False,则层不会使用偏置向量。
- kernel_initializer:权值矩阵(内核)的初始化器。默认为 ‘glorot_uniform’,也称为 Xavier 初始化器。它根据输入和输出单元的数量来初始化权重,以保持每个神经元在前向传播和反向传播中的激活方差一致。
- recurrent_initializer:用于循环内核权重的初始化器。默认为 ‘orthogonal’,它生成一个正交矩阵,这对于避免梯度消失问题很有帮助。
- bias_initializer:偏置向量的初始化器。默认为 ‘zeros’,即将偏置初始化为零。
- dropout:0 到 1 之间的浮点数,表示输入单元的丢弃比例。
- recurrent_dropout:0 到 1 之间的浮点数,表示循环单元的丢弃比例。
- return_sequences:布尔值,表示是否返回每个时间步的输出序列,还是只返回最后一个时间步的输出。默认为 False。
- return_state:布尔值,表示是否返回最后一个时间步的隐藏状态。默认为 False。
- go_backwards:布尔值,表示是否反向处理输入序列。默认为 False。
- stateful:布尔值,表示是否在每个批次结束时重置状态。如果设置为 True,则层的状态将在连续批次的调用之间保持。默认为 False。
- unroll:布尔值,表示是否展开 RNN。如果设置为 True,则 RNN 将被展开成一个全连接的网络,这在某些情况下可以提高效率,尤其是在使用长序列时。默认为 False。
通过调整这些参数,可以定制 SimpleRNN 层以适应不同的序列处理任务。
import tensorflow
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense,LSTM,SimpleRNN
model = Sequential()
model.add(SimpleRNN(200, input_shape=(13,1), activation='relu'))
model.add(Dense(100, activation='relu'))
model.add(Dense(1, activation='sigmoid'))
model.summary()
输出
五、编译模型
opt = tf.keras.optimizers.Adam(learning_rate=1e-4)
model.compile(loss='binary_crossentropy',
optimizer=opt,
metrics="accuracy")
六、训练模型
epochs =100
history = model.fit(x_train,y_train,
epochs=epochs,
batch_size=32,
validation_data=(x_test,y_test),
verbose=1)
输出
七、模型评估
import matplotlib.pyplot as plt
acc = history.history['accuracy']
val_acc = history.history['val_accuracy']
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs_range = range(epochs)
plt.figure(figsize=(14, 4))
plt.subplot(1,2,1)
plt.plot(epochs_range, acc, label='Training Accuracy')
plt.plot(epochs_range, val_acc, label='Validation Accuracy')
plt.legend(loc='lower right')
plt.title('Training and Validation Accuracy')
plt.subplot(1,2,2)
plt.plot(epochs_range, loss, label='Training Loss')
plt.plot(epochs_range, val_loss, label='Validation Loss')
plt.legend(loc='upper right')
plt.title('Training and Validation Loss')
plt.show()
输出
scores = model.evaluate(x_test, y_test, verbose=0)
print("%s:% .2f%%" % (model.metrics_names[1], scores[1]*100))
输出
accuracy: 83.87%