如何存储2D CNN提取的图像特征以训练SVM分类器
嘿,我来一步步帮你搞定从CNN特征提取到SVM分类的全流程,每个环节的细节都给你理清楚:
完整流程:CNN特征提取 + SVM分类
1. 先确保你的CNN模型是训练好的
首先看你的CNN结构,要提取用于SVM的有效特征,前提是这个CNN已经在你的图像数据集上训练过(否则提取的是随机初始化的特征,完全没用)。先把你的模型代码整理好,建议给关键层加个名字,方便后续提取特征:
from keras.models import Sequential from keras.layers import Conv2D, Activation, MaxPooling2D, Flatten, Dense, Dropout model = Sequential() model.add(Conv2D(32, (3, 3), input_shape=(3, 150, 150))) model.add(Activation('relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Conv2D(32, (3, 3))) model.add(Activation('relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Conv2D(64, (3, 3))) model.add(Activation('relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Flatten()) # 把3D特征图转成1D特征向量 model.add(Dense(64, name='feature_layer')) # 给这个特征层命名,方便后续提取 model.add(Activation('relu')) model.add(Dropout(0.5)) model.add(Dense(4)) model.add(Activation('softmax')) # 别忘了先编译并训练模型! # model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy']) # model.fit(train_data, train_labels, epochs=10, batch_size=32)
2. 提取并存储特征
接下来用你提供的特征提取代码,替换layer_name为我们刚才命名的feature_layer(或者你也可以选Flatten层,不过Dense层的特征更凝练):
from keras.models import Model # 指定要提取的特征层名字 layer_name = 'feature_layer' intermediate_layer_model = Model(inputs=model.input, outputs=model.get_layer(layer_name).output) cnn_features = intermediate_layer_model.predict(data) # data是你的图像数据集,形状要匹配(None, 3, 150, 150)
存储特征的两种常用方式
- NumPy保存(推荐小到中等数据集):简单直接,读写速度快
import numpy as np # 分别保存特征和对应的标签 np.save('cnn_features.npy', cnn_features) np.save('image_labels.npy', y) # y是你的图像对应的分类标签(比如0-3的整数)
- Pickle保存(适合把特征和标签存在一个文件):
import pickle # 把特征和标签打包成字典保存 with open('cnn_features_labels.pkl', 'wb') as f: pickle.dump({'features': cnn_features, 'labels': y}, f)
后续加载的时候:
# NumPy加载 features = np.load('cnn_features.npy') y = np.load('image_labels.npy') # Pickle加载 with open('cnn_features_labels.pkl', 'rb') as f: saved_data = pickle.load(f) features = saved_data['features'] y = saved_data['labels']
3. 用train_test_split划分训练/测试集
用sklearn的train_test_split轻松划分数据集,建议设置random_state保证结果可复现:
from sklearn.model_selection import train_test_split # 测试集占比20%,你可以根据需求调整test_size X_train, X_test, y_train, y_test = train_test_split(features, y, test_size=0.2, random_state=42)
4. 训练SVM分类器并评估
最后训练SVM,这里要注意SVM对特征尺度很敏感,建议先做特征归一化,效果会好很多:
from sklearn.svm import SVC from sklearn.preprocessing import StandardScaler from sklearn.metrics import accuracy_score, classification_report # 第一步:特征归一化 scaler = StandardScaler() X_train_scaled = scaler.fit_transform(X_train) X_test_scaled = scaler.transform(X_test) # 第二步:训练SVM clf = SVC() # 你可以调整参数,比如kernel='linear'或者C=10等 clf.fit(X_train_scaled, y_train) # 第三步:预测并评估 y_pred = clf.predict(X_test_scaled) print(f"测试集准确率: {accuracy_score(y_test, y_pred):.2f}") print("\n详细分类报告:") print(classification_report(y_test, y_pred))
进阶小技巧
如果想找到最优的SVM参数,可以用网格搜索:
from sklearn.model_selection import GridSearchCV # 定义要搜索的参数范围 param_grid = {'C': [0.1, 1, 10, 100], 'kernel': ['linear', 'rbf']} # 网格搜索,自动找最优参数 grid_search = GridSearchCV(SVC(), param_grid, refit=True, verbose=2) grid_search.fit(X_train_scaled, y_train) print(f"最优SVM参数: {grid_search.best_params_}") # 用最优模型预测 best_clf = grid_search.best_estimator_ y_pred_best = best_clf.predict(X_test_scaled)
内容的提问来源于stack exchange,提问作者user9165727
相关产品推荐
相关产品推荐

