基于InceptionV3特征提取的SVM训练:大图像数据集优化求助
解决方案
一、解决特征与标签匹配不一致问题
特征和标签错位的核心原因是数据加载时的shuffle打乱了样本顺序,或者提取特征时没有同步记录对应标签。以下是两种可靠解决方法:
方法1:关闭数据加载的shuffle(推荐)
使用tf.keras.utils.image_dataset_from_directory或flow_from_directory时,强制关闭shuffle,确保样本顺序完全一致:
import tensorflow as tf # 加载数据集,关闭shuffle保证顺序匹配 train_ds = tf.keras.utils.image_dataset_from_directory( "训练数据根目录", image_size=image_size, batch_size=BATCH_SIZE, shuffle=False, # 关键设置:禁止打乱顺序 label_mode="int" ) class_names = train_ds.class_names # 获取类别名称映射
提取特征时,遍历数据集批次同步收集特征和标签:
import numpy as np all_features = [] all_labels = [] for batch_imgs, batch_labels in train_ds: batch_feats = model_feat.predict(batch_imgs, verbose=0) all_features.append(batch_feats) all_labels.append(batch_labels.numpy()) # 合并批次结果 all_features = np.concatenate(all_features, axis=0) all_labels = np.concatenate(all_labels, axis=0)
方法2:提前记录样本路径与标签映射(需shuffle时用)
如果必须对数据进行shuffle,提前遍历目录生成样本路径-标签的映射表,后续按映射表顺序提取特征:
import os import pandas as pd # 生成样本信息表 sample_list = [] for class_idx, class_name in enumerate(class_names): class_dir = os.path.join("训练数据根目录", class_name) for img_filename in os.listdir(class_dir): sample_list.append({ "img_path": os.path.join(class_dir, img_filename), "label": class_idx, "class_name": class_name }) sample_df = pd.DataFrame(sample_list) # 自定义图像加载函数 def load_single_image(img_path): img = tf.io.read_file(img_path) img = tf.image.decode_jpeg(img, channels=3) img = tf.image.resize(img, image_size) img = tf.keras.applications.inception_v3.preprocess_input(img) return img # 创建按路径顺序加载的数据集 path_ds = tf.data.Dataset.from_tensor_slices(sample_df["img_path"].values) img_ds = path_ds.map(load_single_image, num_parallel_calls=tf.data.AUTOTUNE) train_ds = img_ds.batch(BATCH_SIZE) # 提取特征后直接用sample_df的标签对应 all_features = model_feat.predict(train_ds) all_labels = sample_df["label"].values all_class_names = sample_df["class_name"].values
二、低GPU占用的数据集处理方案
针对Colab GPU内存有限的问题,核心思路是分批处理+内存复用+CPU卸载,避免全量数据/特征占用GPU或内存:
1. 用tf.data API做轻量化分批处理
利用prefetch和AUTOTUNE优化数据加载,同时控制batch大小避免内存过载:
train_ds = tf.keras.utils.image_dataset_from_directory( "训练数据根目录", image_size=image_size, batch_size=BATCH_SIZE, shuffle=False, label_mode="int" ) # 预取数据,让CPU加载数据和GPU计算并行,减少GPU空闲时间 train_ds = train_ds.prefetch(tf.data.AUTOTUNE)
2. 分批提取特征并逐步写入磁盘
不一次性将全量特征存入内存,处理一批就写入磁盘:
import pandas as pd # 定义特征列名(假设特征是1024维,对应你的Dense(1024)层输出) feature_cols = [f"feat_{i}" for i in range(1024)] # 初始化CSV表头 pd.DataFrame(columns=["label", "class_name"] + feature_cols).to_csv("features_labels.csv", index=False) # 遍历批次处理并追加写入 for batch_imgs, batch_labels in train_ds: batch_feats = model_feat.predict(batch_imgs, verbose=0) # 转换为DataFrame batch_df = pd.DataFrame(batch_feats, columns=feature_cols) batch_df["label"] = batch_labels.numpy() batch_df["class_name"] = [class_names[label] for label in batch_labels.numpy()] # 追加写入CSV(不写表头) batch_df.to_csv("features_labels.csv", mode="a", header=False, index=False)
3. 卸载数据处理到CPU
将特征提取模型和数据加载都移到CPU运行,彻底释放GPU资源:
# 将特征提取模型移到CPU model_feat = model_feat.to("cpu") # 强制数据加载在CPU执行 with tf.device("/cpu:0"): train_ds = tf.keras.utils.image_dataset_from_directory( "训练数据根目录", image_size=image_size, batch_size=BATCH_SIZE, shuffle=False )
三、保存特征与标签到CSV用于t-SNE可视化
上面的分批写入方法已经生成了包含特征、标签、类别名称的CSV文件,直接用该文件做t-SNE即可:
1. 读取CSV并运行t-SNE
from sklearn.manifold import TSNE import matplotlib.pyplot as plt # 读取CSV(数据量大时可分块读取) df = pd.read_csv("features_labels.csv") # 提取特征和标签 features = df[feature_cols].values labels = df["label"].values class_names = df["class_name"].values # 运行t-SNE(可调整perplexity、n_iter等参数优化效果) tsne = TSNE(n_components=2, perplexity=30, random_state=42, n_iter=1000) tsne_results = tsne.fit_transform(features)
2. t-SNE可视化
plt.figure(figsize=(10, 8)) # 按类别绘制散点 unique_classes = df["class_name"].unique() for cls in unique_classes: mask = class_names == cls plt.scatter(tsne_results[mask, 0], tsne_results[mask, 1], label=cls, alpha=0.6) plt.legend() plt.title("t-SNE Visualization of InceptionV3 Features") plt.xlabel("t-SNE Dimension 1") plt.ylabel("t-SNE Dimension 2") plt.show()
内容的提问来源于stack exchange,提问作者partho
相关产品推荐
相关产品推荐

