You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 00:21:25