机器学习3-分类及模型验证

机器分类

人工分类

人自己来分类:
右边比左边大的为1,

       输入          输出
--------------   -----
特征1  特征2
3         1           0
2         5           1
1         8           1
6         4           0
5         2           0
3         5           1
4         7           1
4        -1          0
------------------
6         8           1
5         1           0

代码

# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import numpy as np
import matplotlib.pyplot as mp
x = np.array([
    [3, 1],
    [2, 5],
    [1, 8],
    [6, 4],
    [5, 2],
    [3, 5],
    [4, 7],
    [4, -1]])
y = np.array([0, 1, 1, 0, 0, 1, 1, 0])
l, r, h = x[:, 0].min() - 1, x[:, 0].max() + 1, 0.005
b, t, v = x[:, 1].min() - 1, x[:, 1].max() + 1, 0.005
grid_x = np.meshgrid(np.arange(l, r, h),
                     np.arange(b, t, v))
flat_x = np.c_[grid_x[0].ravel(), grid_x[1].ravel()]
flat_y = np.zeros(len(flat_x), dtype=int)
flat_y[flat_x[:, 0] < flat_x[:, 1]] = 1
grid_y = flat_y.reshape(grid_x[0].shape)
mp.figure('Simple Classification',
          facecolor='lightgray')
mp.title('Simple Classification', fontsize=20)
mp.xlabel('x', fontsize=14)
mp.ylabel('y', fontsize=14)
mp.tick_params(labelsize=10)
mp.pcolormesh(grid_x[0], grid_x[1], grid_y,
              cmap='gray')
mp.scatter(x[:, 0], x[:, 1], c=y, cmap='brg', s=80)
mp.show()

你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。

二元分类

假设预测值y = w0+w1x1+w2x2
在这里插入图片描述
sigmoid函数:激波函数,将连续域分解为离散域
所以将分类问题线性化:
在这里插入图片描述

将预测函数的输出看做输入被划分为1类的概率,择概率大的类别作为预测结果。
根据预测函数得到损失函数,通过梯度下降算法,找到极小值情况的w0…wn,然后将测试样本带入,测试准确率。
model = lm.LogisticRegression(solver=‘liblinear’, C=1)
solver 设置求解系统方程的算法类型:

  • liblinear 用于大型线性分类
  • sag 使用随机平均梯度最小化有限和。
  • saga 支持非强复合目标的快速递增梯度方法

C为正则强度,取值为0->+∞。较小的值制定了更强的正则化
正则强度参考:https://www.cnblogs.com/jianxinzhou/p/4083921.html
代码:

# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import numpy as np
import sklearn.linear_model as lm
import matplotlib.pyplot as mp
x = np.array([
    [3, 1],
    [2, 5],
    [1, 8],
    [6, 4],
    [5, 2],
    [3, 5],
    [4, 7],
    [4, -1]])
y = np.array([0, 1, 1, 0, 0, 1, 1, 0])
# 逻辑分类器
model = lm.LogisticRegression(
    solver='liblinear', C=1)
model.fit(x, y)
l, r, h = x[:, 0].min() - 1, x[:, 0].max() + 1, 0.005
b, t, v = x[:, 1].min() - 1, x[:, 1].max() + 1, 0.005
grid_x = np.meshgrid(np.arange(l, r, h),
                     np.arange(b, t, v))
flat_x = np.c_[grid_x[0].ravel(), grid_x[1].ravel()]
flat_y = model.predict(flat_x)
grid_y = flat_y.reshape(grid_x[0].shape)
mp.figure('Logistic Classification',
          facecolor='lightgray')
mp.title('Logistic Classification', fontsize=20)
mp.xlabel('x', fontsize=14)
mp.ylabel('y', fontsize=14)
mp.tick_params(labelsize=10)
mp.pcolormesh(grid_x[0], grid_x[1], grid_y,
              cmap='gray')
mp.scatter(x[:, 0], x[:, 1], c=y, cmap='brg', s=80)
mp.show()

多元分类


多元分类
   /\
走  不走
           /\
     骑车 不骑车
                   /\
             坐车 不坐车
                           /\
                     开车 不开车
                             ...
                A       B       C
... -> A 1 0.7 0 0.2 0 0.1 -> A
... -> B 0 0.1 1 0.8 0 0.4 -> B
... -> C 0 0.3 0 0.3 1 0.9 -> C


利用分类器模型本身的算法实现多元分类,如决策树。
通过组合多个二元分类的预测结果实现多元分类,如逻辑分类器。
... A 1 0 0
... B 0 1 0
... A 1 0 0
... B 0 1 0
... C 0 0 1
... C 0 0 1
        |  |  |
        |  |  v
        |  v 训练二元分类器Z,其输出值就是属于C类的概率
       v 训练二元分类器Y,其输出值就是属于B类的概率
       训练二元分类器X,其输出值就是属于A类的概率
     X     Y      Z
...  0.7  0.4  0.8 -> C
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import numpy as np
import sklearn.linear_model as lm
import matplotlib.pyplot as mp
x = np.array([
    [4, 7],
    [3.5, 8],
    [3.1, 6.2],
    [0.5, 1],
    [1, 2],
    [1.2, 1.9],
    [6, 2],
    [5.7, 1.5],
    [5.4, 2.2]])
y = np.array([0, 0, 0, 1, 1, 1, 2, 2, 2])
# 创建并训练逻辑分类器
model = lm.LogisticRegression(
    solver='liblinear', C=100)
model.fit(x, y)
# l,r,h:l=第一列最小值-1,r为第一列最大值+1,h为0.005
l, r, h = x[:, 0].min() - 1, x[:, 0].max() + 1, 0.005
# b,t,v:b为第二列最小值-1,t第二列最大值+1,v0.005
b, t, v = x[:, 1].min() - 1, x[:, 1].max() + 1, 0.005
# 根据值画网格
print(l,r,h,sep=" ")
print(b,t,v,sep=' ')
grid_x = np.meshgrid(np.arange(l, r, h), np.arange(b, t, v))
# ravel():返回其一位数组的情况。
# np.r_是按列连接两个矩阵,就是把两矩阵上下相加,要求列数相等,增加其行数,类似于pandas中的concat()。
# np.c_是按行连接两个矩阵,就是把两矩阵左右相加,要求行数相等,增加其列数,类似于pandas中的merge()。
# 上方两种方法均需要一维数组,这里得到所有点的坐标
flat_x = np.c_[grid_x[0].ravel(), grid_x[1].ravel()]
flat_y = model.predict(flat_x)
grid_y = flat_y.reshape(grid_x[0].shape)
mp.figure('Logistic Classification',
          facecolor='lightgray')
mp.title('Logistic Classification', fontsize=20)
mp.xlabel('x', fontsize=14)
mp.ylabel('y', fontsize=14)
mp.tick_params(labelsize=10)
#根据网格给界面划分
mp.pcolormesh(grid_x[0], grid_x[1], grid_y,
              cmap='gray')
#将训练点点上去
mp.scatter(x[:, 0], x[:, 1], c=y, cmap='brg',
           s=60)
mp.show()

朴素贝叶斯分类

朴素:条件堵路
概率:
P(美女,爱你)=P(美女)P(爱你|美女) // 贝叶斯定理
                           1%           1%
10000个人
100美女
1爱你
X样本被划分为C类别的概率:
P(X,C)=
P(x1,x2,x3,C)=P(x1|x2,x3,C)P(x2,x3,C)
     |   \_____/             |  \___/
     v       v                   v v
  爱你      美女                爱你美女
=P(x1|x2,x3,C)P(x2|x3,C)P(x3,C)
=P(x1|x2,x3,C)P(x2|x3,C)P(x3|C)P(C)
   | 朴素:条件独立,特征值之间没有因果关系
   v
=P(x1|C)P(x2|C)P(x3|C)P(C)

根据上面的公式,由训练数据集中统计得到,某个特定类别©的概率,和该类别条件下各个特征值(x1,x2,x3)出现的概率,彼此相乘,就得到有这组特征值构成的样本(X)被划分为该类别©的概率。通过比较不同类别的划分概率,取其最大值作为预测结果。在样本数不足的时候,如果已知样本的特征值服从某种概率分布规则,可以用其概率密度函数或概率质量函数直接求得针对特定特征值计算所需要的概率值。

import sklearn.naive_bayes as nb
# 基于正态分布的朴素贝叶斯分类器
model = nb.GaussianNB()
高斯分布 = 正态分布

代码:

# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import numpy as np
import sklearn.naive_bayes as nb
import matplotlib.pyplot as mp
x, y = [], []
with open(r'C:\Users\Cs\Desktop\机器学习\ML\data\multiple1.txt', 'r') as f:
    for line in f.readlines():
        data = [float(substr) for substr in line.split(',')]
        x.append(data[:-1])
        y.append(data[-1])
x = np.array(x)
y = np.array(y, dtype=int)
# 创建朴素贝叶斯分类器模型
model = nb.GaussianNB()
# 训练朴素贝叶斯分类器模型
model.fit(x, y)
# 点阵水平边界和步长
l, r, h = x[:, 0].min() - 1, x[:, 0].max() + 1, 0.005
# 点阵垂直边界和步长
b, t, v = x[:, 1].min() - 1, x[:, 1].max() + 1, 0.005
# 生成二维点阵
#             _ grid_x
#   ^ |h|    /
# t | * * * *
#   | * * * *-- v
# b | * * * *--
#   +-------->
#     l     r

grid_x = np.meshgrid(np.arange(l, r, h), np.arange(b, t, v))
# 将点阵中每个点的水平坐标和垂直坐标作为
# 样本的两个特征合并成一个两列的二维数组
flat_x = np.c_[grid_x[0].ravel(), grid_x[1].ravel()]
# 利用朴素贝叶斯分类器模型预测点阵的类别
flat_y = model.predict(flat_x)
# 将一维形式的类别变成点阵形式的二维数组
grid_y = flat_y.reshape(grid_x[0].shape)
# 将训练集中的输入代入模型预测其类别输出
pred_y = model.predict(x)
# 计算预测正确的比例,python中,True也是1,可以通过int,求和等方式转换为int格式,
print((pred_y == y).sum() / pred_y.size)
# 绘制训练样本和分类边界
mp.figure('Naive Bayes Classification',
          facecolor='lightgray')
mp.title('Naive Bayes Classification', fontsize=20)
mp.xlabel('x', fontsize=14)
mp.ylabel('y', fontsize=14)
mp.tick_params(labelsize=10)
mp.pcolormesh(grid_x[0], grid_x[1], grid_y,
              cmap='gray')
mp.scatter(x[:, 0], x[:, 1], c=y, cmap='brg',
           s=60)
mp.show()

在这里插入图片描述

训练相关

划分训练集和测试集

之前的训练和测试,总是从同一份样本中取一部分训练一部分测试,这里可以自动划分训练集和测试集。

0 80% 20%
1 80% 20%
2 80% 20%
   |   |
   v   v
  训练 测试
import sklearn.model_selection as ms
ms.train_test_split(输入集, 输出集, test_size=测试集比例,
    random_state=随机种子)
    ->训练输入,测试输入,训练输出,测试输出

在朴素贝叶斯分类中进行测试:

# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import numpy as np
import sklearn.naive_bayes as nb
import matplotlib.pyplot as mp
import sklearn.model_selection as ms
x, y = [], []
with open(r'C:\Users\Cs\Desktop\机器学习\ML\data\multiple1.txt', 'r') as f:
    for line in f.readlines():
        data = [float(substr) for substr in line.split(',')]
        x.append(data[:-1])
        y.append(data[-1])

x = np.array(x)
y = np.array(y, dtype=int)
train_x, test_x, train_y, test_y=ms.train_test_split(x,y,random_state=7,test_size=0.2)
# 创建朴素贝叶斯分类器模型
model = nb.GaussianNB()
# 训练朴素贝叶斯分类器模型
model.fit(train_x,train_y)
# 点阵水平边界和步长
l, r, h = x[:, 0].min() - 1, x[:, 0].max() + 1, 0.005
# 点阵垂直边界和步长
b, t, v = x[:, 1].min() - 1, x[:, 1].max() + 1, 0.005
# 生成二维点阵
#             _ grid_x
#   ^ |h|    /
# t | * * * *
#   | * * * *-- v
# b | * * * *--
#   +-------->
#     l     r

grid_x = np.meshgrid(np.arange(l, r, h), np.arange(b, t, v))
# 将点阵中每个点的水平坐标和垂直坐标作为
# 样本的两个特征合并成一个两列的二维数组
flat_x = np.c_[grid_x[0].ravel(), grid_x[1].ravel()]
# 利用朴素贝叶斯分类器模型预测点阵的类别
flat_y = model.predict(flat_x)
# 将一维形式的类别变成点阵形式的二维数组
grid_y = flat_y.reshape(grid_x[0].shape)
# 将训练集中的输入代入模型预测其类别输出
print(test_x)
pred_y = model.predict(test_x)
# 计算预测正确的比例,python中,True也是1,可以通过int,求和等方式转换为int格式,
print((pred_y == test_y).sum() / pred_y.size)
# 绘制训练样本和分类边界
mp.figure('Naive Bayes Classification',
          facecolor='lightgray')
mp.title('Naive Bayes Classification', fontsize=20)
mp.xlabel('x', fontsize=14)
mp.ylabel('y', fontsize=14)
mp.tick_params(labelsize=10)
mp.pcolormesh(grid_x[0], grid_x[1], grid_y,
              cmap='gray')
mp.scatter(x[:, 0], x[:, 1], c=y, cmap='brg',
           s=60)
mp.show()

交叉验证

交叉验证:分别将数据的不同部分用来训练和测试,得到多个结果,综合之后得到最终结果。
在正式训练模型之前,通过交叉验证评估所选择的模型算法和超参数是否合适,如果指标可以接受那么继续训练,否则更换或调整模型的算法和超参数。
ms.cross_val_score(模型对象,输入,输出,cv=验证次数,
scoring=指标)->每次验证的指标分值数组
指标:
对于A类别
模型判定属于A类别的样本数为C+D,其中C真的属于A类别,而D其实是属于其它类别的。
C/(C+D) - 针对A类别的查准率,对不对
在整个样本空间中A类别的样本共为C+B个,其中C被模型正确识别出来,而B个被模型误判为其它类别。
C/(C+B) - 针对A类别的召回率,全不全
F1得分 = 2x查准率x召回率/(查准率+召回率)
precision_weighted - 查准率
recall_weighted - 召回率 > 取各类别指标的平均值
f1_weighted - F1得分 _______/
accuracy - 正确率

# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import numpy as np
import sklearn.model_selection as ms
import sklearn.naive_bayes as nb
import matplotlib.pyplot as mp
x, y = [], []
with open('../../data/multiple1.txt', 'r') as f:
    for line in f.readlines():
        data = [float(substr) for substr
                in line.split(',')]
        x.append(data[:-1])
        y.append(data[-1])
x = np.array(x)
y = np.array(y, dtype=int)
# 按照3:1的比例划分训练集和测试集
train_x, test_x, train_y, test_y = ms.train_test_split(
    x, y, test_size=0.25, random_state=7)
# 创建朴素贝叶斯分类器模型
model = nb.GaussianNB()
# 通过交叉验证评估模型的可用性
print(ms.cross_val_score(model, x, y, cv=5,scoring='precision_weighted').mean())  # 查准率
print(ms.cross_val_score(model, x, y, cv=5,scoring='recall_weighted').mean())  # 召回率
print(ms.cross_val_score(model, x, y, cv=5,scoring='f1_weighted').mean())  # F1得分
print(ms.cross_val_score(model, x, y, cv=5,scoring='accuracy').mean())  # 正确率
# 用训练集训练朴素贝叶斯分类器模型
model.fit(train_x, train_y)
# 点阵水平边界和步长
l, r, h = x[:, 0].min() - 1, x[:, 0].max() + 1, 0.005
# 点阵垂直边界和步长
b, t, v = x[:, 1].min() - 1, x[:, 1].max() + 1, 0.005
# 生成二维点阵
#             _ grid_x
#   ^ |h|    /
# t | * * * *
#   | * * * *-- v
# b | * * * *--
#   +-------->
#     l     r
grid_x = np.meshgrid(np.arange(l, r, h),
                     np.arange(b, t, v))
# 将点阵中每个点的水平坐标和垂直坐标作为
# 样本的两个特征合并成一个两列的二维数组
flat_x = np.c_[grid_x[0].ravel(), grid_x[1].ravel()]
# 利用朴素贝叶斯分类器模型预测点阵的类别
flat_y = model.predict(flat_x)
# 将一维形式的类别变成点阵形式的二维数组
grid_y = flat_y.reshape(grid_x[0].shape)
# 用测试集验证模型预测结果的正确率
pred_test_y = model.predict(test_x)
print((pred_test_y == test_y).sum() / pred_test_y.size)
# 绘制训练样本和分类边界
mp.figure('Naive Bayes Classification',
          facecolor='lightgray')
mp.title('Naive Bayes Classification', fontsize=20)
mp.xlabel('x', fontsize=14)
mp.ylabel('y', fontsize=14)
mp.tick_params(labelsize=10)
mp.pcolormesh(grid_x[0], grid_x[1], grid_y,
              cmap='gray')
mp.scatter(test_x[:, 0], test_x[:, 1], c=test_y,
           cmap='brg', s=60)
mp.show()

混淆矩阵

sm.confusion_matrix(实际输出, 预测输出)->混淆矩阵
混淆矩阵中的每一行表示实际类别样本数,每一列表示预测类别样本数,主对角线上的元素表示预测正确的样本数。理想混淆矩阵,非主对角线上的元素应该都为0。非主对角线上的元素越多,其值越大,表示模型的精度越差,反之越好。用主对角线上的元素除以其所在列元素之和就是相应类别的查准率。用主对角线上的元素除以其所在行元素之和就是相应类别的召回率。

# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import numpy as np
import sklearn.model_selection as ms
import sklearn.naive_bayes as nb
import sklearn.metrics as sm
import matplotlib.pyplot as mp
x, y = [], []
with open('../../data/multiple1.txt', 'r') as f:
    for line in f.readlines():
        data = [float(substr) for substr
                in line.split(',')]
        x.append(data[:-1])
        y.append(data[-1])
x = np.array(x)
y = np.array(y, dtype=int)
# 按照3:1的比例划分训练集和测试集
train_x, test_x, train_y, test_y = ms.train_test_split(
    x, y, test_size=0.25, random_state=7)
# 创建朴素贝叶斯分类器模型
model = nb.GaussianNB()
# 通过交叉验证评估模型的可用性
print(ms.cross_val_score(
    model, x, y, cv=5,
    scoring='precision_weighted').mean())  # 查准率
print(ms.cross_val_score(
    model, x, y, cv=5,
    scoring='recall_weighted').mean())  # 召回率
print(ms.cross_val_score(
    model, x, y, cv=5,
    scoring='f1_weighted').mean())  # F1得分
print(ms.cross_val_score(
    model, x, y, cv=5,
    scoring='accuracy').mean())  # 正确率
# 用训练集训练朴素贝叶斯分类器模型
model.fit(train_x, train_y)
# 点阵水平边界和步长
l, r, h = x[:, 0].min() - 1, x[:, 0].max() + 1, 0.005
# 点阵垂直边界和步长
b, t, v = x[:, 1].min() - 1, x[:, 1].max() + 1, 0.005
# 生成二维点阵
grid_x = np.meshgrid(np.arange(l, r, h),
                     np.arange(b, t, v))
# 将点阵中每个点的水平坐标和垂直坐标作为
# 样本的两个特征合并成一个两列的二维数组
flat_x = np.c_[grid_x[0].ravel(), grid_x[1].ravel()]
# 利用朴素贝叶斯分类器模型预测点阵的类别
flat_y = model.predict(flat_x)
# 将一维形式的类别变成点阵形式的二维数组
grid_y = flat_y.reshape(grid_x[0].shape)
# 用测试集验证模型预测结果的正确率
pred_test_y = model.predict(test_x)
print((pred_test_y == test_y).sum() / pred_test_y.size)
# 通过混淆矩阵检验模型的预测结果
cm = sm.confusion_matrix(test_y, pred_test_y)
print(cm)
# 绘制训练样本和分类边界
mp.figure('Naive Bayes Classification',
          facecolor='lightgray')
mp.title('Naive Bayes Classification', fontsize=20)
mp.xlabel('x', fontsize=14)
mp.ylabel('y', fontsize=14)
mp.tick_params(labelsize=10)
mp.pcolormesh(grid_x[0], grid_x[1], grid_y,
              cmap='gray')
mp.scatter(test_x[:, 0], test_x[:, 1], c=test_y,
           cmap='brg', s=60)
mp.figure('Confusion Matrix', facecolor='lightgray')
mp.title('Confusion Matrix', fontsize=20)
mp.xlabel('Predicted Class', fontsize=14)
mp.ylabel('True Class', fontsize=14)
mp.xticks(np.unique(pred_test_y))
mp.yticks(np.unique(test_y))
mp.tick_params(labelsize=10)
mp.imshow(cm, interpolation='nearest', cmap='jet')
mp.show()

分类报告

sm.classification_report(实际输出, 预测输出)->分类报告
计算每个类别的查准率、召回率和F1得分,极其平均值。

# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import numpy as np
import sklearn.model_selection as ms
import sklearn.naive_bayes as nb
import sklearn.metrics as sm
import matplotlib.pyplot as mp
x, y = [], []
with open(r'C:\Users\Cs\Desktop\机器学习\ML\data\multiple1.txt', 'r') as f:
    for line in f.readlines():
        data = [float(substr) for substr
                in line.split(',')]
        x.append(data[:-1])
        y.append(data[-1])
x = np.array(x)
y = np.array(y, dtype=int)
# 按照3:1的比例划分训练集和测试集
train_x, test_x, train_y, test_y = ms.train_test_split(
    x, y, test_size=0.25, random_state=7)
# 创建朴素贝叶斯分类器模型
model = nb.GaussianNB()
model.fit(train_x, train_y)
# 用测试集验证模型预测结果的正确率
pred_test_y = model.predict(test_x)
print((pred_test_y == test_y).sum() / pred_test_y.size)
# 通过分类报告展示模型的预测结果
cr = sm.classification_report(test_y, pred_test_y)
print(cr)

结果

        #     查准率         召回率    f1得分    样本数量
              precision    recall  f1-score   support

           0       1.00      1.00      1.00        22
           1       1.00      0.96      0.98        28
           2       0.96      1.00      0.98        25
           3       1.00      1.00      1.00        25

   micro avg       0.99      0.99      0.99       100
   macro avg       0.99      0.99      0.99       100
weighted avg       0.99      0.99      0.99       100 加权平均

基于决策树的分类

基于投票的决策

基于决策树的分类与回归的区别就在于,预测结果的获取,是通过投票而非平均得到的。

命中子表
… A
… B |
… A |
… B > A:2<B:4
… B |
… B /
x -> B

# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import numpy as np
import sklearn.preprocessing as sp
import sklearn.ensemble as se
import sklearn.model_selection as ms
data = []
with open('../../data/car.txt', 'r') as f:
    for line in f.readlines():
        data.append(line[:-1].split(','))
data = np.array(data).T
encoders, train_x = [], []
for row in range(len(data)):
    encoder = sp.LabelEncoder()
    if row < len(data) - 1:
        train_x.append(
            encoder.fit_transform(data[row]))
    else:
        train_y = encoder.fit_transform(data[row])
    encoders.append(encoder)
train_x = np.array(train_x).T
# 随机森林分类器,n_estimatorsj决策树个数。
model = se.RandomForestClassifier(
    max_depth=8, n_estimators=200, random_state=7)
print(ms.cross_val_score(
    model, train_x, train_y, cv=5,
    scoring='f1_weighted').mean())
model.fit(train_x, train_y)
data = [
    ['high', 'med', '5more', '4', 'big', 'low'],
    ['high', 'high', '4', '4', 'med', 'med'],
    ['low', 'low', '2', '2', 'small', 'high'],
    ['low', 'med', '4', '4', 'med', 'high']]
data = np.array(data).T
test_x = []
for row in range(len(data)):
    encoder = encoders[row]
    test_x.append(encoder.transform(data[row]))
test_x = np.array(test_x).T
pred_test_y = model.predict(test_x)
print(encoders[-1].inverse_transform(pred_test_y))

验证曲线

模型对象 = 学习模型类(超参数序列)
    \__________________/
    性能       |     选择
           验证曲线
ms.validation_curve(
    模型对象, 输入集, 输出集, 超参数名, 超参数取值序列,
    cv=验证次数)->训练集F1得分矩阵, 测试集F1得分矩阵

矩阵:一行对应一个超参数取值,一列对应一次交叉验证
如果测试集分值足够高,理想参数,如果测试集分值较低同时训练集分值也较低,说明欠拟合,反之如果测试集分值较低但是训练集分值却较高,说明过拟合。

max_depth 1      2      3      4      5      mean
4               0.89  0.99 0.76 0.89 0.92 -------> 0.85
5                                                                         0.88
6                                                                         0.92 *
7                                                                         0.83
8                                                                         0.79

代码:

# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import numpy as np
import sklearn.preprocessing as sp
import sklearn.ensemble as se
import sklearn.model_selection as ms
import matplotlib.pyplot as mp
data = []
with open('../../data/car.txt', 'r') as f:
    for line in f.readlines():
        data.append(line[:-1].split(','))
data = np.array(data).T
encoders, x = [], []
for row in range(len(data)):
    encoder = sp.LabelEncoder()
    if row < len(data) - 1:
        x.append(
            encoder.fit_transform(data[row]))
    else:
        y = encoder.fit_transform(data[row])
    encoders.append(encoder)
x = np.array(x).T
# 获得关于n_estimators的验证曲线
model = se.RandomForestClassifier(
    max_depth=6, random_state=7)
n_estimators = np.arange(50, 550, 50)
train_scores, test_scores = ms.validation_curve(
    model, x, y, 'n_estimators', n_estimators, cv=5)
train_means1 = train_scores.mean(axis=1)
for param, score in zip(n_estimators, train_means1):
    print(param, '->', score)
# 获得关于max_depth的验证曲线
model = se.RandomForestClassifier(
    n_estimators=200, random_state=7)
max_depth = np.arange(1, 11)
train_scores, test_scores = ms.validation_curve(
    model, x, y, 'max_depth', max_depth, cv=5)
train_means2 = train_scores.mean(axis=1)
for param, score in zip(max_depth, train_means2):
    print(param, '->', score)
mp.figure('n_estimators', facecolor='lightgray')
mp.title('n_estimators', fontsize=20)
mp.xlabel('n_estimators', fontsize=14)
mp.ylabel('F1 Score', fontsize=14)
mp.tick_params(labelsize=10)
mp.grid(linestyle=':')
mp.plot(n_estimators, train_means1, 'o-',
        c='dodgerblue', label='Training')
mp.legend()
mp.figure('max_depth', facecolor='lightgray')
mp.title('max_depth', fontsize=20)
mp.xlabel('max_depth', fontsize=14)
mp.ylabel('F1 Score', fontsize=14)
mp.tick_params(labelsize=10)
mp.grid(linestyle=':')
mp.plot(max_depth, train_means2, 'o-',
        c='dodgerblue', label='Training')
mp.legend()
mp.show()

学习曲线

基础理解
学习曲线作用:查看模型的学习效果;
通过学习曲线可以清晰的看出模型对数据的过拟合和欠拟合;
学习曲线:随着训练样本的逐渐增多,算法训练出的模型的表现能力
表现能力:也就是模型的预测准确率,使用均方误差表示;学习率上体现了模型相对于训练集和测试集两类数据的均方误差。

学习曲线:模型性能 = f(训练集大小)
ms.learning_curve(模型, 输入集, 输出集,
    train_sizes=训练集大小序列,cv=验证次数\折叠数)
    ->训练集大小序列, 训练集得分, 测试集得分
训练集大小序列=[0.9 0.8 0.7 0.6 0.5]
         CV1 CV2 ...
0.9->0.9   0.7  ... ->mean()
0.8->0.6   0.8  ... ->mean() <- max
...^
   |
 best
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import numpy as np
import sklearn.preprocessing as sp
import sklearn.ensemble as se
import sklearn.model_selection as ms
import matplotlib.pyplot as mp
data = []
with open(r'C:\Users\Cs\Desktop\机器学习\ML\data\car.txt', 'r') as f:
    for line in f.readlines():
        data.append(line[:-1].split(','))
data = np.array(data).T
encoders, x = [], []
for row in range(len(data)):
    # 将一列字符串形式的特征值,按照字典排序,用每个字符在排序序列中的索引号表示该字符。
    encoder = sp.LabelEncoder()
    if row < len(data) - 1:
        x.append(
            encoder.fit_transform(data[row]))
    else:
        y = encoder.fit_transform(data[row])
    encoders.append(encoder)
x = np.array(x).T
# 获得学习曲线
model = se.RandomForestClassifier(
    max_depth=9, n_estimators=200, random_state=7)
train_sizes = np.linspace(0.1, 1, 10)
print(train_sizes)
_, train_scores, test_scores = ms.learning_curve(
    model, x, y, train_sizes=train_sizes, cv=5)
train_means = train_scores.mean(axis=1)
for size, score in zip(train_sizes, train_means):
    print(size, '->', score)
mp.figure('Learning Curve', facecolor='lightgray')
mp.title('Learning Curve', fontsize=20)
mp.xlabel('train_size', fontsize=14)
mp.ylabel('F1 Score', fontsize=14)
mp.tick_params(labelsize=10)
mp.grid(linestyle=':')
mp.plot(train_sizes, train_means, 'o-',
        c='dodgerblue', label='Training')
mp.legend()
mp.show()

过拟合与欠拟合解决

◆训练集误差大、交叉验证集误差也大:欠拟合、高偏差、多项式次数d太小、λ太大;

◆训练集误差小、交叉验证集误差却很大:过拟合、高方差、多项式次数d太大、λ太下、样本量太少。

提出的六种可选的下一步,让我们来看一看我们在什么情况下应该怎样选择:

  1. 获得更多的训练实例——解决高方差
  2. 尝试减少特征的数量——解决高方差
  3. 尝试获得更多的特征——解决高偏差
  4. 尝试增加多项式特征——解决高偏差
  5. 尝试减少归一化程度 λ——解决高偏差
  6. 尝试增加归一化程度 λ——解决高方差

猜你喜欢

转载自blog.csdn.net/weixin_36179862/article/details/85010200