-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdata_preprocessing.py
More file actions
179 lines (145 loc) · 5.93 KB
/
Copy pathdata_preprocessing.py
File metadata and controls
179 lines (145 loc) · 5.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
import os
import numpy as np
import pandas as pd
from PIL import Image
import tensorflow as tf
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from sklearn.model_selection import KFold
import matplotlib.pyplot as plt
import seaborn as sns
class DataPreprocessor:
"""数据预处理类,负责图像数据的加载、预处理和数据增强"""
def __init__(self, train_dir='train', img_size=(128, 128), batch_size=128):
self.train_dir = train_dir
self.img_size = img_size
self.batch_size = batch_size
self.class_names = ['cat', 'dog']
def load_data_info(self):
"""加载数据集信息"""
files = os.listdir(self.train_dir)
cats = [f for f in files if f.startswith('cat')]
dogs = [f for f in files if f.startswith('dog')]
print(f"数据集统计:")
print(f"猫的图片数量: {len(cats)}")
print(f"狗的图片数量: {len(dogs)}")
print(f"总图片数量: {len(files)}")
return len(cats), len(dogs), len(files)
def create_dataframe(self):
"""创建包含文件路径和标签的DataFrame"""
files = os.listdir(self.train_dir)
data = []
for file in files:
if file.startswith('cat'):
label = 0 # cat
elif file.startswith('dog'):
label = 1 # dog
else:
continue
data.append({
'filename': file,
'filepath': os.path.join(self.train_dir, file),
'label': label,
'class_name': 'cat' if label == 0 else 'dog'
})
df = pd.DataFrame(data)
return df
def create_data_generators(self, train_df, val_df):
"""创建训练和验证数据生成器 - 简化数据增强"""
# 简化训练数据增强,减少计算量
train_datagen = ImageDataGenerator(
rescale=1./255,
rotation_range=15, # 减少旋转范围
horizontal_flip=True,
zoom_range=0.1, # 减少缩放范围
fill_mode='nearest'
)
# 验证数据只进行标准化
val_datagen = ImageDataGenerator(rescale=1./255)
# 创建训练生成器
train_generator = train_datagen.flow_from_dataframe(
train_df,
x_col='filepath',
y_col='class_name',
target_size=self.img_size,
batch_size=self.batch_size,
class_mode='binary',
shuffle=True
)
# 创建验证生成器
val_generator = val_datagen.flow_from_dataframe(
val_df,
x_col='filepath',
y_col='class_name',
target_size=self.img_size,
batch_size=self.batch_size,
class_mode='binary',
shuffle=False
)
return train_generator, val_generator
def split_data_kfold(self, df, n_splits=3, random_state=42):
"""使用K折交叉验证分割数据 - 减少折数以加快实验"""
kfold = KFold(n_splits=n_splits, shuffle=True, random_state=random_state)
folds = []
for fold_idx, (train_idx, val_idx) in enumerate(kfold.split(df)):
train_df = df.iloc[train_idx].reset_index(drop=True)
val_df = df.iloc[val_idx].reset_index(drop=True)
folds.append({
'fold': fold_idx + 1,
'train_df': train_df,
'val_df': val_df,
'train_size': len(train_df),
'val_size': len(val_df)
})
print(f"Fold {fold_idx + 1}: 训练集 {len(train_df)} 张, 验证集 {len(val_df)} 张")
return folds
def visualize_data_distribution(self, df):
"""可视化数据分布"""
plt.figure(figsize=(12, 4))
# 类别分布
plt.subplot(1, 2, 1)
class_counts = df['class_name'].value_counts()
plt.pie(class_counts.values, labels=class_counts.index, autopct='%1.1f%%')
plt.title('类别分布')
# 类别计数
plt.subplot(1, 2, 2)
sns.countplot(data=df, x='class_name')
plt.title('各类别图片数量')
plt.ylabel('数量')
plt.tight_layout()
plt.savefig('data_distribution.png', dpi=300, bbox_inches='tight')
plt.show()
def sample_images(self, df, n_samples=8):
"""展示样本图片"""
fig, axes = plt.subplots(2, 4, figsize=(16, 8))
axes = axes.ravel()
# 每个类别采样一半
cat_samples = df[df['class_name'] == 'cat'].sample(n_samples//2)
dog_samples = df[df['class_name'] == 'dog'].sample(n_samples//2)
samples = pd.concat([cat_samples, dog_samples])
for idx, (_, row) in enumerate(samples.iterrows()):
img = Image.open(row['filepath'])
img = img.resize(self.img_size)
axes[idx].imshow(img)
axes[idx].set_title(f"{row['class_name']}")
axes[idx].axis('off')
plt.tight_layout()
plt.savefig('sample_images.png', dpi=300, bbox_inches='tight')
plt.show()
if __name__ == "__main__":
# 测试数据预处理功能
preprocessor = DataPreprocessor()
# 加载数据信息
preprocessor.load_data_info()
# 创建数据框
df = preprocessor.create_dataframe()
print(f"\n数据框形状: {df.shape}")
print(f"数据框列名: {df.columns.tolist()}")
print(f"\n前5行数据:")
print(df.head())
# 可视化数据分布
preprocessor.visualize_data_distribution(df)
# 展示样本图片
preprocessor.sample_images(df)
# K折交叉验证分割
folds = preprocessor.split_data_kfold(df, n_splits=3)
print(f"\n成功创建 {len(folds)} 个交叉验证折")