为何不同标注掩码训练的sklearn RandomForest模型预测速度存在差异
问题描述
我在使用sklearn的RandomForestClassifier过程中遇到了一个无法理解的问题。
我构建了一个像素级分类模型,用于判断每个像素是否对应目标物体(本次测试目标为梨),效果示例如下:
我使用以下三张图片作为训练集:
目前我针对相同的训练图像,使用两种不同的标注掩码分别训练了两个模型:
- 模型1标注掩码:

- 模型2标注掩码:

两个模型的准确率均符合要求,但存在明显的速度差异:模型1对10张新图像完成预测仅耗时约0.5秒,模型2对相同10张图像预测耗时约4秒,请问该现象的成因是什么?
应@TYZ建议补充代码及更多信息如下:
def train_model(image_path, labeled_image_path, test_split=0.3): train_img = cv2.imread(image_path) #加载训练图像 train_img = cv2.cvtColor(train_img, cv2.COLOR_BGR2RGB) #转换BGR格式为RGB train_img = train_img[:, :, 2] #仅保留绿色通道(调试后选择的效果最优通道) df = generate_features(train_img) #生成包含所有特征的DataFrame train_img_labeled = cv2.imread(labeled_image_path) train_img_labeled = cv2.cvtColor(train_img_labeled, cv2.COLOR_BGR2GRAY) #加载标注图像 df["Labels"] = train_img_labeled.reshape(-1) Y = df["Labels"].values X = df.drop(labels=["Labels"], axis=1) # 拆分训练集和测试集 from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=test_split, random_state=20) # 初始化模型 from sklearn.ensemble import RandomForestClassifier model = RandomForestClassifier(n_estimators = 5, random_state = 25, max_depth=1, n_jobs=1) # 训练模型 model.fit(X_train, y_train) return model
def test(model): image_paths = ["test/scaled/test_1.jpeg", "test/scaled/test_2.jpeg", "test/scaled/test_3.jpeg", "test/scaled/test_4.jpeg", "test/scaled/test_5.jpeg", "test/scaled/test_6.jpeg", "test/scaled/test_7.jpeg", "test/scaled/test_8.jpeg", "test/scaled/test_9.jpeg", "test/scaled/test_10.jpeg"] import time start_time = time.time() for image_path in image_paths: start_time = time.time() result = calculate_model_output(model, image_path, show=False) print("--- %s seconds ---" % (time.time()-start_time))

原因及解决方案
核心原因是两个模型的分类任务类型存在本质差异
你加载标注掩码时直接将灰度图的像素值作为模型标签,没有做二值化处理,导致两个模型的分类类别数差异极大:
- 模型1的标注掩码是纯二值图像,仅包含背景(灰度值0)和梨(灰度值255)两类,属于二分类任务,随机森林预测时仅需判断每个像素属于正负类,计算量极小
- 模型2的标注掩码存在多个不同灰度值,可能是标注了多个梨实例、存在边界过渡灰度、或是标注噪声引入了额外类别,属于多分类任务。随机森林预测时需要为每个类别计算输出概率再取最大值,类别数越多耗时越高,8倍的耗时差正好匹配多分类场景的计算量增长规律。
验证方法
你可以直接打印两个模型的classes_属性确认类别数差异:
print("模型1类别数:", len(model1.classes_)) print("模型2类别数:", len(model2.classes_))
修复方案
确认后只需要在标注加载步骤增加二值化处理,就能统一两个模型的任务类型,消除速度差异:
# 加载灰度标注后增加二值化逻辑,统一转为二分类标签 train_img_labeled = cv2.threshold(train_img_labeled, 127, 255, cv2.THRESH_BINARY)[1]
另外你当前的测试代码存在计时bug:循环内部每次都重置了start_time,所以打印的耗时其实只有第10张图的预测耗时,不是10张图的总耗时,把循环内的start_time = time.time()删掉即可修复。
内容的提问来源于stack exchange,提问作者Marc Teixidó
相关产品推荐
相关产品推荐

