【机器学习】 自定义数据集 使用tensorflow框架实现逻辑回归并保存模型,然后保存模型后再加载模型进行预测
一、使用tensorflow框架实现逻辑回归
1. 数据部分:
- 首先自定义了一个简单的数据集,特征
X
是 100 个随机样本,每个样本一个特征,目标值y
基于线性关系并添加了噪声。 - tensorflow框架不需要
numpy
数组转换为相应的张量,可以直接在模型中使用数据集。
2. 模型定义部分:
方案 1:model = tf.keras.Sequential([tf.keras.layers.Dense(1, input_shape=(1,))])
解释:
- 此方案使用
tf.keras.Sequential
构建模型,在列表中直接定义了一个Dense
层,input_shape=(1,)
表明输入数据的形状。 - 编译模型时,选择随机梯度下降(SGD)优化器和均方误差损失函数。
- 训练完成后,使用
sklearn
的指标评估模型,并输出模型的系数和截距。
import tensorflow as tf
import numpy as np
from sklearn.metrics import mean_squared_error, r2_score
# 自定义数据集
X = np.random.rand(100, 1).astype(np.float32)
y = 2 * X + 1 + 0.3 * np.random.randn(100, 1).astype(np.float32)
# 构建模型
model = tf.keras.Sequential([
tf.keras.layers.Dense(1, input_shape=(1,))
])
# 编译模型
model.compile(optimizer=tf.keras.optimizers.SGD(learning_rate=0.01),
loss='mean_squared_error')
# 训练模型
history = model.fit(X, y, epochs=1000, verbose=0)
# 模型评估
y_pred = model.predict(X)
mse = mean_squared_error(y, y_pred)
r2 = r2_score(y, y_pred)
print(f"均方误差 (MSE): {mse}")
print(f"决定系数 (R²): {r2}")
# 输出模型的系数和截距
weights, biases = model.layers[0].get_weights()
print(f"模型系数: {weights[0][0]}")
print(f"模型截距: {biases[0]}")
方案 2:model = tf.keras.Sequential()
解释:
- 这种方式先创建一个空的
Sequential
模型,再使用add
方法添加Dense
层。 - 后续编译、训练、评估和输出模型参数的步骤与方案 1 类似。
import tensorflow as tf
import numpy as np
from sklearn.metrics import mean_squared_error, r2_score
# 自定义数据集
X = np.random.rand(100, 1).astype(np.float32)
y = 2 * X + 1 + 0.3 * np.random.randn(100, 1).astype(np.float32)
# 构建模型
model = tf.keras.Sequential()
model.add(tf.keras.layers.Dense(1, input_shape=(1,)))
# 编译模型
model.compile(optimizer=tf.keras.optimizers.SGD(learning_rate=0.01),
loss='mean_squared_error')
# 训练模型
history = model.fit(X, y, epochs=1000, verbose=0)
# 模型评估
y_pred = model.predict(X)
mse = mean_squared_error(y, y_pred)
r2 = r2_score(y, y_pred)
print(f"均方误差 (MSE): {mse}")
print(f"决定系数 (R²): {r2}")
# 输出模型的系数和截距
weights, biases = model.layers[0].get_weights()
print(f"模型系数: {weights[0][0]}")
print(f"模型截距: {biases[0]}")
方案 3:自定义模型类
解释:
- 继承
Model
基类创建自定义模型类Linear
,在__init__
方法中定义Dense
层。 call
方法用于实现前向传播逻辑,类似于 PyTorch 中的forward
方法。- 后续的编译、训练、评估和参数输出流程和前面方案一致。
import tensorflow as tf
from tensorflow.keras import Model
import numpy as np
from sklearn.metrics import mean_squared_error, r2_score
# 自定义数据集
X = np.random.rand(100, 1).astype(np.float32)
y = 2 * X + 1 + 0.3 * np.random.randn(100, 1).astype(np.float32)
# 自定义模型类
class Linear(Model):
def __init__(self):
super(Linear, self).__init__()
self.linear = tf.keras.layers.Dense(1)
def call(self, x, **kwargs):
x = self.linear(x)
return x
# 构建模型
model = Linear()
# 编译模型
model.compile(optimizer=tf.keras.optimizers.SGD(learning_rate=0.01),
loss='mean_squared_error')
# 训练模型
history = model.fit(X, y, epochs=1000, verbose=0)
# 模型评估
y_pred = model.predict(X)
mse = mean_squared_error(y, y_pred)
r2 = r2_score(y, y_pred)
print(f"均方误差 (MSE): {mse}")
print(f"决定系数 (R²): {r2}")
# 输出模型的系数和截距
weights, biases = model.linear.get_weights()
print(f"模型系数: {weights[0][0]}")
print(f"模型截距: {biases[0]}")
方案 4:函数式 API 构建模型
解释:
- 使用函数式 API 构建模型,先定义输入层,再定义
Dense
层,最后使用Model
类将输入和输出连接起来形成模型。 - 编译、训练、评估和参数输出的步骤和前面方案相同。注意这里通过
model.layers[1]
获取Dense
层的权重和偏置,因为第一层是输入层。
import tensorflow as tf
import numpy as np
from sklearn.metrics import mean_squared_error, r2_score
# 自定义数据集
X = np.random.rand(100, 1).astype(np.float32)
y = 2 * X + 1 + 0.3 * np.random.randn(100, 1).astype(np.float32)
# 定义函数构建模型
def linear():
input = tf.keras.layers.Input(shape=(1,), dtype=tf.float32)
y = tf.keras.layers.Dense(1)(input)
model = tf.keras.models.Model(inputs=input, outputs=y)
return model
# 构建模型
model = linear()
# 编译模型
model.compile(optimizer=tf.keras.optimizers.SGD(learning_rate=0.01),
loss='mean_squared_error')
# 训练模型
history = model.fit(X, y, epochs=1000, verbose=0)
# 模型评估
y_pred = model.predict(X)
mse = mean_squared_error(y, y_pred)
r2 = r2_score(y, y_pred)
print(f"均方误差 (MSE): {mse}")
print(f"决定系数 (R²): {r2}")
# 输出模型的系数和截距
weights, biases = model.layers[1].get_weights()
print(f"模型系数: {weights[0][0]}")
print(f"模型截距: {biases[0]}")
3. 训练和评估部分:
- 使用
fit
方法对模型进行训练,verbose=0
表示不显示训练过程中的详细信息,训练过程中的损失信息会存储在history
对象中。 - 通过多个 epoch 进行训练,每个 epoch 包含前向传播、损失计算、反向传播和参数更新。
- 使用
predict
方法进行预测,计算均方误差和决定系数评估模型性能,通过model.linear.get_weights()
获取模型的系数和截距。
二、保存tensorflow框架逻辑回模型
方式 1:保存为 HDF5 文件(后缀名 .h5
)
这种方式会保存模型的结构、权重以及训练配置(如优化器、损失函数等),加载时可以直接得到一个完整可用的模型。
import tensorflow as tf
import numpy as np
# 自定义数据集
# 生成 1000 个样本,每个样本有 2 个特征
X = np.random.randn(1000, 2).astype(np.float32)
# 根据特征生成标签
y = (2 * X[:, 0] + 3 * X[:, 1] > 0).astype(np.float32).reshape(-1, 1)
# 构建逻辑回归模型
model = tf.keras.Sequential([
tf.keras.layers.Dense(1, input_shape=(2,), activation='sigmoid')
])
# 编译模型
model.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy'])
# 训练模型
model.fit(X, y, epochs=100, batch_size=32, verbose=1)
# 保存模型为 HDF5 文件
model.save('logistic_regression_model.h5')
# 加载 HDF5 文件模型
loaded_model = tf.keras.models.load_model('logistic_regression_model.h5')
# 生成新的测试数据
X_test = np.random.randn(100, 2).astype(np.float32)
y_test = (2 * X_test[:, 0] + 3 * X_test[:, 1] > 0).astype(np.float32).reshape(-1, 1)
# 进行预测
y_pred_probs = loaded_model.predict(X_test)
y_pred = (y_pred_probs > 0.5).astype(np.float32)
# 计算准确率
accuracy = tf.keras.metrics.BinaryAccuracy()
accuracy.update_state(y_test, y_pred)
print(f"预测准确率: {accuracy.result().numpy()}")
代码解释
- 数据生成与模型构建:生成自定义数据集,构建并编译逻辑回归模型,然后进行训练。
- 保存模型:使用
model.save('logistic_regression_model.h5')
将模型保存为 HDF5 文件。 - 加载模型:使用
tf.keras.models.load_model('logistic_regression_model.h5')
加载保存的模型。 - 预测与评估:生成新的测试数据,使用加载的模型进行预测,并计算预测准确率。
方式 2:只保存参数
这种方式只保存模型的权重参数,不保存模型的结构和训练配置。加载时需要先定义与原模型相同结构的模型,再将保存的参数加载到新模型中。
import tensorflow as tf
import numpy as np
# 自定义数据集
# 生成 1000 个样本,每个样本有 2 个特征
X = np.random.randn(1000, 2).astype(np.float32)
# 根据特征生成标签
y = (2 * X[:, 0] + 3 * X[:, 1] > 0).astype(np.float32).reshape(-1, 1)
# 构建逻辑回归模型
model = tf.keras.Sequential([
tf.keras.layers.Dense(1, input_shape=(2,), activation='sigmoid')
])
# 编译模型
model.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy'])
# 训练模型
model.fit(X, y, epochs=100, batch_size=32, verbose=1)
# 只保存模型参数
model.save_weights('logistic_regression_weights.h5')
# 重新定义相同结构的模型
new_model = tf.keras.Sequential([
tf.keras.layers.Dense(1, input_shape=(2,), activation='sigmoid')
])
# 编译新模型
new_model.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy'])
# 加载保存的参数到新模型
new_model.load_weights('logistic_regression_weights.h5')
# 生成新的测试数据
X_test = np.random.randn(100, 2).astype(np.float32)
y_test = (2 * X_test[:, 0] + 3 * X_test[:, 1] > 0).astype(np.float32).reshape(-1, 1)
# 进行预测
y_pred_probs = new_model.predict(X_test)
y_pred = (y_pred_probs > 0.5).astype(np.float32)
# 计算准确率
accuracy = tf.keras.metrics.BinaryAccuracy()
accuracy.update_state(y_test, y_pred)
print(f"预测准确率: {accuracy.result().numpy()}")
代码解释
- 数据生成与模型构建:同样生成自定义数据集,构建并编译逻辑回归模型,进行训练。
- 保存参数:使用
model.save_weights('logistic_regression_weights.h5')
只保存模型的权重参数。 - 重新定义模型:重新定义一个与原模型结构相同的新模型,并进行编译。
- 加载参数:使用
new_model.load_weights('logistic_regression_weights.h5')
将保存的参数加载到新模型中。 - 预测与评估:生成新的测试数据,使用加载参数后的新模型进行预测,并计算预测准确率。
通过以上两种方式,可以根据实际需求选择合适的模型保存方法。
三、加载tensorflow框架逻辑回归模型
方案 1:加载保存为 HDF5 文件的模型
当用户将模型保存为 HDF5 文件(后缀名 .h5
)时,使用 tf.keras.models.load_model
函数可以直接加载整个模型,包括模型的结构、权重以及训练配置。
import tensorflow as tf
import numpy as np
# 生成一些示例数据用于预测
X_test = np.random.randn(100, 2).astype(np.float32)
y_test = (2 * X_test[:, 0] + 3 * X_test[:, 1] > 0).astype(np.float32).reshape(-1, 1)
# 加载保存为 HDF5 文件的模型
loaded_model = tf.keras.models.load_model('logistic_regression_model.h5')
# 进行预测
y_pred_probs = loaded_model.predict(X_test)
y_pred = (y_pred_probs > 0.5).astype(np.float32)
# 计算准确率
accuracy = tf.keras.metrics.BinaryAccuracy()
accuracy.update_state(y_test, y_pred)
print(f"预测准确率: {accuracy.result().numpy()}")
代码解释
- 数据准备:生成一些示例数据
X_test
和对应的标签y_test
,用于后续的预测和评估。 - 模型加载:使用
tf.keras.models.load_model('logistic_regression_model.h5')
加载之前保存为 HDF5 文件的模型。 - 预测与评估:使用加载的模型对测试数据进行预测,将预测概率转换为标签,然后计算预测准确率。
方案 2:加载只保存的参数(权重和偏置)
当用户只保存了模型的参数(权重和偏置)时,需要先定义一个与原模型结构相同的新模型,然后使用 load_weights
方法将保存的参数加载到新模型中。
import tensorflow as tf
import numpy as np
# 生成一些示例数据用于预测
X_test = np.random.randn(100, 2).astype(np.float32)
y_test = (2 * X_test[:, 0] + 3 * X_test[:, 1] > 0).astype(np.float32).reshape(-1, 1)
# 重新定义相同结构的模型
new_model = tf.keras.Sequential([
tf.keras.layers.Dense(1, input_shape=(2,), activation='sigmoid')
])
# 编译新模型
new_model.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy'])
# 加载保存的参数
new_model.load_weights('logistic_regression_weights.h5')
# 进行预测
y_pred_probs = new_model.predict(X_test)
y_pred = (y_pred_probs > 0.5).astype(np.float32)
# 计算准确率
accuracy = tf.keras.metrics.BinaryAccuracy()
accuracy.update_state(y_test, y_pred)
print(f"预测准确率: {accuracy.result().numpy()}")
代码解释
- 数据准备:同样生成示例数据
X_test
和y_test
用于预测和评估。 - 模型定义与编译:重新定义一个与原模型结构相同的新模型
new_model
,并进行编译,设置优化器、损失函数和评估指标。 - 参数加载:使用
new_model.load_weights('logistic_regression_weights.h5')
将之前保存的参数加载到新模型中。 - 预测与评估:使用加载参数后的新模型对测试数据进行预测,将预测概率转换为标签,最后计算预测准确率。
通过以上两种方案,可以根据不同的保存方式正确加载 TensorFlow 模型。
四、完整流程
1. 实现思路
① 导入必要的库
在开始之前,需要导入 TensorFlow 用于构建和训练模型,NumPy 用于数据处理,以及一些评估指标相关的库。
② 生成自定义数据集
自定义数据集可以根据具体需求生成,这里以一个简单的二维数据集为例,每个样本有两个特征,标签为 0 或 1。
③ 构建逻辑回归模型
一共有4种方式,案例使用其中的TensorFlow的tf.keras.Sequential
构建模型,在列表中直接定义了一个 Dense
层,input_shape=(1,)
表明输入数据的形状。
④ 训练模型
使用生成的数据集对模型进行训练。
⑤ 保存模型
可以选择将模型保存为 HDF5 文件或只保存模型的参数,案例为保存为 HDF5 文件。
⑥ 加载模型并进行预测
此案例为加载 HDF5 文件模型
2. 代码示例
import tensorflow as tf
import numpy as np
from sklearn.metrics import accuracy_score
# 生成 1000 个样本,每个样本有 2 个特征
X = np.random.randn(1000, 2).astype(np.float32)
# 根据特征生成标签
y = (2 * X[:, 0] + 3 * X[:, 1] > 0).astype(np.float32).reshape(-1, 1)
# 构建逻辑回归模型
model = tf.keras.Sequential([
tf.keras.layers.Dense(1, input_shape=(2,), activation='sigmoid')
])
# 编译模型
model.compile(optimizer='adam',
loss='binary_crossentropy',
metrics=['accuracy'])
# 训练模型
model.fit(X, y, epochs=100, batch_size=32, verbose=1)
# 保存模型
model.save('logistic_regression_model')
# 加载模型
loaded_model = tf.keras.models.load_model('logistic_regression_model')
# 生成新的测试数据
X_test = np.random.randn(100, 2).astype(np.float32)
y_test = (2 * X_test[:, 0] + 3 * X_test[:, 1] > 0).astype(np.float32).reshape(-1, 1)
# 进行预测
y_pred_probs = loaded_model.predict(X_test)
y_pred = (y_pred_probs > 0.5).astype(np.float32)
# 计算准确率
accuracy = accuracy_score(y_test, y_pred)
print(f"预测准确率: {accuracy}")
3. 代码解释
① 数据集生成:
使用 np.random.randn
生成具有两个特征的随机样本,根据特征的线性组合生成标签。
② 模型构建:
使用 tf.keras.Sequential
构建一个简单的逻辑回归模型,包含一个具有 sigmoid
激活函数的全连接层。
③ 模型编译:
使用 adam
优化器和 binary_crossentropy
损失函数进行编译,并监控准确率指标。
④ 模型训练:
使用 fit
方法对模型进行训练,指定训练轮数和批次大小。
⑤ 模型保存:
使用 model.save
方法将模型保存到指定目录。
⑥ 模型加载与预测:
使用 tf.keras.models.load_model
加载保存的模型,生成新的测试数据进行预测,并计算预测准确率。