分析代码是做什么的,并给代码做出注释,将其完整代码列出
时间: 2024-10-23 09:06:55 浏览: 27
### 代码分析与注释
该代码实现了一个用于图像分类的卷积神经网络(CNN)模型,具体步骤如下:
1. **导入必要的库**:包括操作系统操作、JSON处理、NumPy、Pandas、PIL、TensorFlow、Scikit-learn等。
2. **加载数据**:从指定目录读取图像文件,并从JSON文件中读取对应的标签。
3. **预处理数据**:将图像数据归一化,并将标签转换为数值形式。
4. **划分训练集和验证集**:使用`train_test_split`函数将数据分为训练集和验证集。
5. **构建模型**:定义一个简单的CNN模型,包括多个卷积层、池化层、全连接层和Dropout层。
6. **编译模型**:设置优化器、损失函数和评估指标。
7. **数据增强**:使用`ImageDataGenerator`进行数据增强,增加模型的泛化能力。
8. **训练模型**:使用生成的数据增强器训练模型。
9. **评估模型**:在验证集上评估模型的性能,计算准确率和F1分数。
10. **预测并保存结果**:对测试集进行预测,并将结果保存到CSV文件中。
### 完整代码及注释
```python
import os
import json
import numpy as np
import pandas as pd
from PIL import Image
import tensorflow as tf
from sklearn.model_selection import train_test_split
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Dropout
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.optimizers import Adam
from sklearn.metrics import f1_score, accuracy_score
def load_data(data_dir, label_path):
"""
加载图像数据和对应标签
:param data_dir: 图像文件所在目录
:param label_path: 标签文件路径
:return: 图像数组和标签数组
"""
with open(label_path, 'r') as f:
labels_list = json.load(f)
# 打印前几个元素以检查数据结构
print("Labels list structure:")
print(labels_list[:5])
labels = {item['文件名']: item['标签'] for item in labels_list if '文件名' in item and '标签' in item}
images = []
targets = []
for file_name, label in labels.items():
img_path = os.path.join(data_dir, file_name)
# 检查文件是否存在
if not os.path.exists(img_path):
print(f"Warning: Image file {img_path} does not exist.")
continue
img = Image.open(img_path).resize((128, 128))
img_array = np.array(img) / 255.0 # 归一化
images.append(img_array)
targets.append(label)
if len(images) == 0:
raise ValueError("No valid images found. Please check the data directory and label path.")
return np.array(images), np.array(targets)
data_dir = "C:\\Users\\24067\\Desktop\\peach_split\\train"
label_path = "C:\\Users\\24067\\Desktop\\train_label.json"
try:
images, labels = load_data(data_dir, label_path)
except ValueError as e:
print(e)
exit()
# 将标签转换为数值
label_map = {'特级': 3, '一级': 2, '二级': 1, '三级': 0}
labels = np.array([label_map[label] for label in labels])
# 划分训练集和验证集
X_train, X_val, y_train, y_val = train_test_split(images, labels, test_size=0.2, random_state=42)
def create_model(input_shape=(128, 128, 3)):
"""
创建卷积神经网络模型
:param input_shape: 输入图像的形状
:return: Keras模型
"""
model = Sequential([
Conv2D(32, (3, 3), activation='relu', input_shape=input_shape),
MaxPooling2D((2, 2)),
Conv2D(64, (3, 3), activation='relu'),
MaxPooling2D((2, 2)),
Conv2D(128, (3, 3), activation='relu'),
MaxPooling2D((2, 2)),
Flatten(),
Dense(128, activation='relu'),
Dropout(0.5),
Dense(4, activation='softmax')
])
return model
model = create_model()
model.compile(optimizer=Adam(learning_rate=0.001), loss='sparse_categorical_crossentropy', metrics=['accuracy'])
datagen = ImageDataGenerator(
rotation_range=20,
width_shift_range=0.2,
height_shift_range=0.2,
horizontal_flip=True,
vertical_flip=True
)
history = model.fit(datagen.flow(X_train, y_train, batch_size=32), epochs=1, validation_data=(X_val, y_val))
def evaluate_model(model, X, y):
"""
评估模型性能
:param model: 训练好的Keras模型
:param X: 验证集特征
:param y: 验证集标签
:return: 准确率和F1分数
"""
predictions = model.predict(X)
predicted_labels = np.argmax(predictions, axis=1)
accuracy = accuracy_score(y, predicted_labels)
f1 = f1_score(y, predicted_labels, average='weighted')
print(f'Accuracy: {accuracy:.4f}')
print(f'F1 Score: {f1:.4f}')
return accuracy, f1
evaluate_model(model, X_val, y_val)
def predict_and_save(test_data_dir, test_label_path, output_path):
"""
对测试集进行预测并将结果保存到CSV文件
:param test_data_dir: 测试图像文件所在目录
:param test_label_path: 测试标签文件路径
:param output_path: 结果输出文件路径
"""
test_images = []
test_file_names = []
with open(test_label_path, 'r') as f:
test_labels_list = json.load(f)
# 打印前几个元素以检查数据结构
print("Test labels list structure:")
print(test_labels_list[:5])
test_labels = {item['文件名']: item['标签'] for item in test_labels_list if '文件名' in item and '标签' in item}
for file_name in test_labels.keys():
img_path = os.path.join(test_data_dir, file_name)
# 检查文件是否存在
if not os.path.exists(img_path):
print(f"Warning: Test image file {img_path} does not exist.")
continue
img = Image.open(img_path).resize((128, 128))
img_array = np.array(img) / 255.0
test_images.append(img_array)
test_file_names.append(file_name)
test_images = np.array(test_images)
predictions = model.predict(test_images)
predicted_labels = np.argmax(predictions, axis=1)
label_map_inv = {v: k for k, v in label_map.items()}
predicted_labels = [label_map_inv[label] for label in predicted_labels]
submission_df = pd.DataFrame({'file_name': test_file_names, 'label': predicted_labels})
submission_df.to_csv(output_path, index=False)
test_data_dir = "C:\\Users\\24067\\Desktop\\peach_split\\val"
test_label_path = "C:\\Users\\24067\\Desktop\\val_label.json"
output_path = "submission.csv"
predict_and_save(test_data_dir, test_label_path, output_path)
```
### 关键点总结
- **数据加载**:从指定目录和JSON文件中读取图像和标签。
- **数据预处理**:图像归一化,标签转换为数值。
- **模型构建**:定义一个简单的CNN模型。
- **数据增强**:使用`ImageDataGenerator`进行数据增强。
- **模型训练**:使用增强后的数据训练模型。
- **模型评估**:在验证集上评估模型性能。
- **结果保存**:对测试集进行预测并将结果保存到CSV文件中。
阅读全文