随机森林

随机森林(Random Forest)是一种集成学习方法,它通过构建多个决策树并将它们的预测结果进行汇总来提高预测的准确性和稳定性。在手写数字识别任务中,随机森林可以非常有效地从图像数据(通常是像素值)中学习并分类数字。下面,我将指导你如何使用Python和scikit-learn库来实现基于随机森林的手写数字识别:

  1. 训练模型
  2. 测试模型

实现手写数字识别

参数

首先介绍一下随机森林中包含的参数,便于了解使用随机森林:

class sklearn.ensemble.RandomForestClassifier(n_estimators=’warn’, criterion=’gini’, max_depth=None, min_samples_split=2, min_samples_leaf=1, min_weight_fraction_leaf=0.0, max_features=’auto’, max_leaf_nodes=None, min_impurity_decrease=0.0, min_impurity_split=None, bootstrap=True, oob_score=False, n_jobs=None, random_state=None, verbose=0, warm_start=False, class_weight=None)

这么多参数中,主要的有:

n_estimators:随机森林中决策树的个数。在0.20版本中默认是10个决策树;在0.22版本中默认是100个决策树;

max_features:随机森林允许单个决策树使用特征的最大数量。选择最适属性时划分的特征不能超过此值。当为整数时,即最大特征数;当为小数时,训练集特征数*小数;

random_state:确定随机种子

训练模型

  1. 收集数据
    在这里插入图片描述

  2. 读取图片

使用opencv处理图片,将图片的像素数值读取进来,并返回的是一个三维(高,宽,颜色)numpy数组:

 pip install opencv-python==3.4.11.45
import cv2
img = cv2.imread("digits.png")
  1. 转为灰度图

将图片转化为灰度图,从而让三维数组变成二位的数组:

grey = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
  1. 处理图片信息

对图片进行处理:将其先垂直切分(横向)成50份,再将每一份水平切分(竖向)成100份,这样我们的每份图片的像素值都为20*20(训练的图片比较规范)共500个,比如:

在这里插入图片描述

import numpy as np
img_info = [np.hsplit(row,100) for row in np.vsplit(grey,50)]
  1. 装进array数组

将切分的每一份图片像素数据都装进array数组中:

x = np.array(img_info)
  1. 分隔训练集与测试集

将数据分为两份,一份为训练集,一份作为测试集:

train_x = x[:,:80]
test_x = x[:,80:100]
  1. 调整数据结构

由于我们最后要将数据放在随机森林模型中训练,我们得将数据结构调整为适合随机森林算法训练的结构,那么我们就来改变每份图片数组的维度:reshape:

new_train_x = train_x.reshape(-1,400).astype(np.float32)
new_test_x = test_x.reshape(-1,400).astype(np.float32)
  1. 分配标签

我们训练着那么多的数据,却没有给他们具体的类别标签(图像的实际值),因为我们之前的图像处理都是在寻找图像特征,但是并没有给他们一个具体对应的类别,只有空荡荡的特征,无法分类,所以我们得给切分的每份图片打上它们对应的标签:

k = np.arange(10)
train_y = np.repeat(k,400)
test_y = np.repeat(k,100)
train_y = train_y.ravel()
  1. 交叉验证

在随机森林的算法中,主要通过调整决策树的个数n_estimators、最大数量特征max_features以及随机种子,我们要进行调参数,看看哪个参数最为合适,使模型拟合效果更好:

from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score
mf = [0.5,0.6,0.7,0.8,0.9]
scores = []
for i in mf:
    rf = RandomForestClassifier(
        n_estimators=100,
        max_features=i,
        random_state=0
    )
    score = cross_val_score(rf,new_train_x,train_y,cv=10,scoring='recall_macro')
    sco_mean = sum(score)/len(score)
    scores.append(sco_mean)
mf_choose = mf[np.argmax(max(scores))]
print('最优最大数量特征:',mf_choose)
----------------------
最优最大数量特征: 0.5

除此之外,决策树模型中还可以调整的参数有:

max_depth:设置决策树的最大深度,默认为None。

  1. 训练模型
rf_model = RandomForestClassifier(
    n_estimators=100,
    max_features=mf_choose,
    random_state=0
)
rf_model.fit(new_train_x,train_y)

测试模型

  1. 先用训练数据再次进入模型测试,查看他本身的模型训练效果怎么样:
from sklearn import metrics
train_predict = rf_model.predict(new_train_x)
print(metrics.classification_report(train_y,train_predict)) #查看混淆矩阵
-------------------------------
              precision    recall  f1-score   support

           0       1.00      1.00      1.00       400
           1       1.00      1.00      1.00       400
           2       1.00      1.00      1.00       400
           3       1.00      1.00      1.00       400
           4       1.00      1.00      1.00       400
           5       1.00      1.00      1.00       400
           6       1.00      1.00      1.00       400
           7       1.00      1.00      1.00       400
           8       1.00      1.00      1.00       400
           9       1.00      1.00      1.00       400

    accuracy                           1.00      4000
   macro avg       1.00      1.00      1.00      4000
weighted avg       1.00      1.00      1.00      4000

  1. 再用分割的测试集来测试模型:
test_predict = rf_model.predict(new_test_x)
print(metrics.classification_report(test_y,test_predict))
---------------------------
              precision    recall  f1-score   support

           0       0.99      0.68      0.80       100
           1       0.97      1.00      0.99       100
           2       0.86      0.89      0.88       100
           3       0.84      0.93      0.88       100
           4       0.93      0.94      0.94       100
           5       0.83      0.81      0.82       100
           6       0.90      0.97      0.93       100
           7       0.99      0.93      0.96       100
           8       0.84      0.94      0.89       100
           9       0.92      0.93      0.93       100

    accuracy                           0.90      1000
   macro avg       0.91      0.90      0.90      1000
weighted avg       0.91      0.90      0.90      1000

我们也可以尝试调整其他参数,查看结果,动手试试吧!

到这为止!!我们就训练好一个关于手写数字识别的决策树模型啦!!

总结

本篇介绍了如何用随机森林实现手写数字识别:

  1. 注意对读取的数据处理
  2. 学会调整参数,优化模型,比如本篇在交叉验证中找寻最优的最大特征数量。
Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐