import pandas as pd import numpy as np import seaborn as sns import matplotlib.pyplot as plt %matplotlib inline import tensorflow as tf import random from cv2 import resize from glob import glob import warnings warnings.filterwarnings("ignore")img_height = 244 img_width = 244 train_ds = tf.keras.utils.image_dataset_from_directory( 'D:/Faulty_solar_panel', validation_split=0.2, subset='training', image_size=(img_height, img_width), batch_size=32, seed=42, shuffle=True) val_ds = tf.keras.utils.image_dataset_from_directory( 'D:/Faulty_solar_panel', validation_split=0.2, subset='validation', image_size=(img_height, img_width), batch_size=32, seed=42, shuffle=True)class_names = train_ds.class_names print(class_names) train_dsbase_model = tf.keras.applications.VGG16( include_top=False, weights='imagenet', input_shape=(img_height, img_width, 3) ) base_model.trainable = False inputs = tf.keras.Input(shape=(img_height, img_width, 3)) x = tf.keras.applications.vgg16.preprocess_input(inputs) x = base_model(x, training=False) x = tf.keras.layers.GlobalAveragePooling2D()(x) x = tf.keras.layers.Dropout(0.3)(x) outputs = tf.keras.layers.Dense(90)(x) model = tf.keras.Model(inputs, outputs) model.summary()model.compile(optimizer=tf.keras.optimizers.Adam(0.001), loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True), metrics=['accuracy'])epoch = 15 model.fit(train_ds, validation_data=val_ds, epochs=epoch, callbacks = [ tf.keras.callbacks.EarlyStopping( monitor="val_loss", min_delta=1e-2, patience=3, verbose=1, restore_best_weights=True ) ] )# fine tuning base_model.trainable = True for layer in base_model.layers[:14]: layer.trainable = False model.summary()model.compile(optimizer=tf.keras.optimizers.Adam(0.0001), loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True), metrics=['accuracy'])epoch = 15 history = model.fit(train_ds, validation_data=val_ds, epochs=epoch, callbacks = [ tf.keras.callbacks.EarlyStopping( monitor="val_loss", min_delta=1e-2, patience=3, verbose=1, ) ] ) get_ac = history.history['accuracy'] get_los = history.history['loss'] val_acc = history.history['val_accuracy'] val_loss = history.history['val_loss'] epochs = range(len(get_ac)) plt.plot(epochs, get_ac, 'g', label='Accuracy of Training data') plt.plot(epochs, get_los, 'r', label='Loss of Training data') plt.title('Training data accuracy and loss') plt.legend(loc=0) plt.figure() plt.plot(epochs, get_ac, 'g', label='Accuracy of Training Data') plt.plot(epochs, val_acc, 'r', label='Accuracy of Validation Data') plt.title('Training and Validation Accuracy') plt.legend(loc=0) plt.figure() plt.plot(epochs, get_los, 'g', label='Loss of Training Data') plt.plot(epochs, val_loss, 'r', label='Loss of Validation Data') plt.title('Training and Validation Loss') plt.legend(loc=0) plt.figure() plt.show()改进代码,使用更好的模型,给出完整的改进后代码
时间: 2025-07-14 11:58:38 浏览: 9
<think>好的,我需要帮助用户改进他们的太阳能电池板缺陷检测的TensorFlow代码。首先,我得仔细阅读他们提供的代码,理解当前的结构和可能的问题。
用户当前的代码使用了VGG16作为基础模型,进行了迁移学习,先冻结了所有层,然后在微调时解冻了部分层。他们可能希望提升模型的性能,所以需要选择一个更好的模型,比如更高效的架构,比如EfficientNet或ResNet50。这些模型在ImageNet上表现更好,可能更适合他们的任务。
接下来,观察数据预处理部分。用户使用了VGG16的预处理函数,但如果换用其他模型,比如EfficientNet,需要调整预处理方法,比如使用tf.keras.applications.efficientnet.preprocess_input。同时,检查数据加载是否正确,是否应用了数据增强,当前的代码中没有看到数据增强的步骤,这可能是改进的一个点。加入数据增强可以提高模型的泛化能力,比如随机旋转、翻转、缩放等。
然后看模型结构。用户添加了全局平均池化、Dropout和全连接层。可能需要调整这些层的参数,比如增加更多的全连接层,或者调整Dropout的比例以防止过拟合。另外,输出层的单元数是90,这可能与他们的分类类别数不符,需要根据实际的class_names数量调整,用户之前的代码中打印的class_names可能只有几个类别,所以这里可能存在错误,需要修正。
编译和训练部分,用户用了Adam优化器,学习率0.001,之后微调时降低到0.0001。可能可以考虑使用不同的学习率调度策略,比如ReduceLROnPlateau来自动调整学习率。另外,检查EarlyStopping的设置,是否合理,比如patience和min_delta的值是否合适。
在微调阶段,用户解冻了base_model的前14层,但如果是换成了EfficientNet,可能需要解冻不同的层数,通常建议微调顶部的部分层。同时,在微调时是否重新编译模型,调整学习率,这些步骤是否正确。
评估部分,用户绘制了准确率和损失曲线,但可能需要更详细的评估,比如混淆矩阵、分类报告等,来更好地了解模型的表现。
综合以上分析,改进的步骤可能包括:
1. 更换基础模型为EfficientNetB4或其他更高效的模型。
2. 添加数据增强层,如图像旋转、翻转、亮度调整等。
3. 调整模型结构,确保输出层的单元数与类别数一致。
4. 优化学习率调度和早停策略。
5. 在微调阶段合理选择解冻的层数。
6. 添加更详细的模型评估和可视化。
现在需要将这些改进点整合到代码中,确保每一步都正确无误,比如导入正确的预处理函数,调整输入形状(如果需要),修改模型构建部分,添加数据增强层,调整全连接层,设置合适的回调函数等。同时,确保代码的完整性和可运行性,比如检查路径是否正确,数据加载是否正常,是否有语法错误等。
最后,测试改进后的代码,确保能够正常运行,并且性能有所提升。可能还需要建议用户根据实际数据集的情况调整超参数,如学习率、批次大小、数据增强的参数等。</think>以下是改进后的完整代码(基于EfficientNet模型+数据增强+学习率调度+更系统的评估):
```python
import tensorflow as tf
from tensorflow.keras import layers, optimizers, callbacks
import matplotlib.pyplot as plt
import numpy as np
# 设置随机种子保证可重复性
SEED = 42
tf.random.set_seed(SEED)
np.random.seed(SEED)
# 数据增强层
data_augmentation = tf.keras.Sequential([
layers.RandomFlip("horizontal_and_vertical", seed=SEED),
layers.RandomRotation(0.2, seed=SEED),
layers.RandomZoom(0.2, seed=SEED),
layers.RandomContrast(0.1, seed=SEED)
])
# 图像尺寸设置
IMG_SIZE = (224, 224) # EfficientNet标准输入尺寸
BATCH_SIZE = 32
# 加载数据集
train_ds = tf.keras.utils.image_dataset_from_directory(
'D:/Faulty_solar_panel',
validation_split=0.2,
subset='training',
seed=SEED,
image_size=IMG_SIZE,
batch_size=BATCH_SIZE,
label_mode='int'
)
val_ds = tf.keras.utils.image_dataset_from_directory(
'D:/Faulty_solar_panel',
validation_split=0.2,
subset='validation',
seed=SEED,
image_size=IMG_SIZE,
batch_size=BATCH_SIZE,
label_mode='int'
)
# 获取类别信息
class_names = train_ds.class_names
NUM_CLASSES = len(class_names)
print(f"检测到 {NUM_CLASSES} 个类别: {class_names}")
# 配置数据集性能优化
AUTOTUNE = tf.data.AUTOTUNE
train_ds = train_ds.cache().prefetch(buffer_size=AUTOTUNE)
val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)
# 构建改进模型
def build_model():
# 使用EfficientNetB4作为基础模型
base_model = tf.keras.applications.EfficientNetB4(
include_top=False,
weights='imagenet',
input_shape=(*IMG_SIZE, 3)
)
# 冻结基础模型
base_model.trainable = False
inputs = layers.Input(shape=(*IMG_SIZE, 3))
x = data_augmentation(inputs) # 数据增强
x = tf.keras.applications.efficientnet.preprocess_input(x)
x = base_model(x, training=False)
x = layers.GlobalAveragePooling2D()(x)
x = layers.Dropout(0.5)(x)
x = layers.Dense(256, activation='relu')(x)
x = layers.BatchNormalization()(x)
outputs = layers.Dense(NUM_CLASSES, activation='softmax')(x)
model = tf.keras.Model(inputs, outputs)
# 初始编译配置
model.compile(
optimizer=optimizers.Adam(learning_rate=1e-3),
loss=tf.keras.losses.SparseCategoricalCrossentropy(),
metrics=['accuracy']
)
return model
model = build_model()
model.summary()
# 训练回调函数配置
early_stopping = callbacks.EarlyStopping(
monitor='val_loss',
patience=5,
min_delta=1e-3,
restore_best_weights=True
)
reduce_lr = callbacks.ReduceLROnPlateau(
monitor='val_loss',
factor=0.2,
patience=3,
min_lr=1e-6
)
# 初始训练阶段
print("\n--- 初始训练阶段 ---")
initial_epochs = 15
history = model.fit(
train_ds,
validation_data=val_ds,
epochs=initial_epochs,
callbacks=[early_stopping, reduce_lr]
)
# 微调阶段
print("\n--- 微调阶段 ---")
# 解冻部分层
model.layers[4].trainable = True # 解冻基础模型
for layer in model.layers[4].layers[: -10]: # 解冻最后10层之前的层
layer.trainable = False
# 重新编译以应用低学习率
model.compile(
optimizer=optimizers.Adam(learning_rate=1e-5),
loss=tf.keras.losses.SparseCategoricalCrossentropy(),
metrics=['accuracy']
)
# 继续训练
fine_tune_epochs = 10
total_epochs = initial_epochs + fine_tune_epochs
history_fine = model.fit(
train_ds,
validation_data=val_ds,
initial_epoch=history.epoch[-1],
epochs=total_epochs,
callbacks=[early_stopping, reduce_lr]
)
# 可视化训练过程
def plot_training_curves(history):
acc = history.history['accuracy']
val_acc = history.history['val_accuracy']
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs_range = range(len(acc))
plt.figure(figsize=(12, 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()
plot_training_curves(history_fine)
# 模型评估
print("\n--- 模型评估 ---")
loss, accuracy = model.evaluate(val_ds)
print(f"最终验证准确率: {accuracy:.2%}")
print(f"最终验证损失: {loss:.4f}")
# 保存模型
model.save('./solar_panel_model_v2.h5')
print("模型已保存为 solar_panel_model_v2.h5")
```
主要改进点说明:
1. **模型架构升级**:
- 使用EfficientNetB4替代VGG16,具有更好的特征提取能力和更高效的参数利用率
- 增加了BatchNormalization层提升训练稳定性
- 优化全连接层结构(256神经元+BN层)
2. **数据增强**:
```python
data_augmentation = tf.keras.Sequential([
layers.RandomFlip("horizontal_and_vertical"),
layers.RandomRotation(0.2),
layers.RandomZoom(0.2),
layers.RandomContrast(0.1)
])
```
包含翻转、旋转、缩放和对比度调整,增强模型泛化能力
3. **训练优化**:
- 添加学习率调度器`ReduceLROnPlateau`
- 改进EarlyStopping策略(patience=5)
- 分阶段训练(初始训练+微调)
- 使用更小的微调学习率(1e-5)
4. **性能优化**:
```python
train_ds = train_ds.cache().prefetch(buffer_size=AUTOTUNE)
val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)
```
使用缓存和预取提升数据加载效率
5. **评估可视化**:
- 改进的训练曲线可视化
- 添加详细模型评估指标
使用建议:
1. 确保数据集目录结构正确:
```
Faulty_solar_panel/
├── class1/
├── class2/
└── .../
```
2. 根据显存情况可调整:
- `BATCH_SIZE`(当前设为32)
- `IMG_SIZE`(当前224x224)
3. 如果类别数较少(如2类),可减少全连接层维度(当前256)
4. 最终模型保存为HDF5格式,方便后续部署使用
可以通过添加测试集评估、混淆矩阵可视化、Grad-CAM热力图分析等方法进一步扩展功能。
阅读全文
相关推荐



















