机器学习模型仅训练数据测试有效,新图像预测错误求助
问题
我正在开发一款基于图像数据的机器学习模型,用于对3种不同类型的表面粗糙度(Type 1、Type 2、Type 3)进行分类。训练数据集包含每种粗糙度类型的5组2D图像(1024*768)和3D点云数据,总计15张图像与15组点云。下方代码在使用训练数据测试时结果正确,但测试新图像时输出错误结果,恳请技术协助:
import numpy as np import os import cv2 from sklearn.model_selection import train_test_split from sklearn.svm import SVC data = [] labels = [] # Loop through the three types of surface roughness types for i in range(1, 4): type_path = f"D:\\Ph.D. IEE\\Research\\My research\\Images\\type{i}" # Loop through the 5 images and point clouds for each type for j in range(1, 6): # Read in the image and point cloud files image_path = os.path.join(type_path, f"{j}.png") point_cloud_path = os.path.join(type_path, f"{j}.csv") image = cv2.imread(image_path) point_cloud = np.loadtxt(point_cloud_path, delimiter='\t') # Append the image and point cloud to the data list data.append((image, point_cloud)) # Append the label to the labels list labels.append(i) # Convert the data and labels lists to NumPy arrays data = np.array(data) labels = np.array(labels) # Split the dataset into training and testing sets train_data, test_data, train_labels, test_labels = train_test_split(data, labels, test_size=0.2, random_state=42) # Reshape the training and testing data train_images = train_data[:, 0] train_images = np.array([cv2.resize(img, (1024, 768)) for img in train_images]) train_point_clouds = train_data[:, 1] train_labels = np.array(train_labels) test_images = test_data[:, 0] test_images = np.array([cv2.resize(img, (1024, 768)) for img in test_images]) test_point_clouds = test_data[:, 1] test_labels = np.array(test_labels) # Train a machine learning model on the training data svm_model = SVC(kernel='linear') svm_model.fit(train_images.reshape(-1, 1024*768*3), train_labels) # Make a prediction on a testing image test_image_path = "D:\\Ph.D. IEE\\Research\\My research\\Test\\t6.png" test_image = cv2.imread(test_image_path) test_image = cv2.resize(test_image, (1024, 768)) prediction = svm_model.predict(test_image.reshape(1, -1))[0] # Map the prediction to the corresponding surface roughness type if prediction == 1: print("The testing image falls under surface roughness type 1.") elif prediction == 2: print("The testing image falls under surface roughness type 2.") elif prediction == 3: print("The testing image falls under surface roughness type 3.") else: print("The trained model could not predict the surface roughness. ")
解决方案
1. 修复循环缩进错误
代码中嵌套循环的缩进完全错误:外层遍历类型的for i循环没有包裹内层的for j循环,导致内层循环只会遍历最后一个类型(Type3)的5组数据,训练数据实际上只有5组而非15组,模型根本没学到前两类的特征。
修正后的循环代码:
for i in range(1, 4): type_path = f"D:\\Ph.D. IEE\\Research\\My research\\Images\\type{i}" # Loop through the 5 images and point clouds for each type for j in range(1, 6): # Read in the image and point cloud files image_path = os.path.join(type_path, f"{j}.png") point_cloud_path = os.path.join(type_path, f"{j}.csv") image = cv2.imread(image_path) point_cloud = np.loadtxt(point_cloud_path, delimiter='\t') # Append the image and point cloud to the data list data.append((image, point_cloud)) # Append the label to the labels list labels.append(i)
2. 利用点云数据提升特征维度
当前模型完全忽略了点云数据,只使用了图像特征。点云包含的3D表面信息对粗糙度分类至关重要,必须将图像特征和点云特征融合后再输入模型。
处理方式示例:
- 先提取点云的统计特征(如高度均值、方差、粗糙度参数Ra/Rz等),将其转为固定长度的向量
- 将图像的像素特征(展平后的向量)与点云统计特征拼接,作为模型的输入特征
示例代码片段:
# 定义点云特征提取函数 def extract_point_cloud_features(pc): # 假设点云是N×3的数组(x,y,z),提取z方向的统计特征 z_values = pc[:, 2] features = [ np.mean(z_values), np.std(z_values), np.max(z_values) - np.min(z_values), np.median(z_values) ] return np.array(features) # 训练时融合特征 train_image_features = train_images.reshape(-1, 1024*768*3) train_pc_features = np.array([extract_point_cloud_features(pc) for pc in train_point_clouds]) train_combined_features = np.hstack([train_image_features, train_pc_features]) # 测试时同样处理 test_image_features = test_images.reshape(-1, 1024*768*3) test_pc_features = np.array([extract_point_cloud_features(pc) for pc in test_point_clouds]) test_combined_features = np.hstack([test_image_features, test_pc_features]) # 用融合特征训练模型 svm_model.fit(train_combined_features, train_labels)
3. 解决数据量过小导致的过拟合问题
仅15组训练数据,模型很容易过拟合训练集,导致对新数据泛化能力极差。
解决方法:
- 数据增强:对图像进行旋转、翻转、噪声添加、亮度调整等操作,扩充图像数据集;对点云可进行轻微的坐标扰动、下采样/上采样增强
- 使用正则化:给SVM添加正则化参数,比如
SVC(kernel='linear', C=0.1),C值越小正则化越强,抑制过拟合 - 换用更适合小数据的模型:比如使用预训练的CNN模型(如ResNet、VGG)提取图像特征,再结合点云特征训练分类器,预训练模型自带的通用特征能大幅提升泛化能力
4. 统一数据预处理流程
- 确保测试图像的预处理和训练图像完全一致:比如图像的颜色空间(当前用cv2.imread读入的是BGR,是否需要转为RGB?)、归一化操作(训练时是否对像素值做了0-1归一化?测试时也要同步做)
- 示例:训练和测试时都添加像素归一化
# 训练图像归一化 train_images = train_images / 255.0 # 测试图像同样归一化 test_image = test_image / 255.0
5. 验证模型性能
训练后要在拆分的test_data上验证模型准确率,而不是仅用训练数据测试。添加验证代码:
# 验证模型在测试集上的表现 test_pred = svm_model.predict(test_combined_features) accuracy = np.mean(test_pred == test_labels) print(f"测试集准确率:{accuracy:.2f}")
内容的提问来源于stack exchange,提问作者Zlatan
相关产品推荐
相关产品推荐

