机器学习----04

朴素贝叶斯分类

分类报告

sklearn.metrics提供了分类报告相关API, 不仅可以得到混淆矩阵, 还可以得到交叉验证的查准率, 召回率, f1得分的结果. 这样可以方便的分析出那些样本是异常样本.

import sklearn.metrics as sm
# 获取分类报告
cr = sm.classification_report(实际输出, 预测输出)
print(cr)

决策树分类

决策树分类模型会找到与样本特征匹配的叶子节点, 然后以投票的方式进行分类.

案例: 基于决策树分类算法, 训练模型, 预测小汽车(car.txt)等级. 需要注意的是每一个特征都需要使用标签编码做预处理.

import numpy as np
import sklearn.preprocessing as sp
import sklearn.ensemble as se
import sklearn.model_selection as ms

data = np.loadtxt('./car.txt', delimiter=',', dtype='U10')

data = data.T
encoders = []
train_x, train_y = [], []

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
# 基于随机森林分类器完成模型训练
model = se.RandomForestClassifier(max_depth=6, n_estimators=200, random_state=7)
print(ms.cross_val_score(model, train_x, train_y, cv=4, scoring='f1_weighted').mean())
model.fit(train_x, train_y)
# 造一些测试数据, 进行测试
data = [
    ['high', 'med', '5more', '4', 'big', 'low', 'unacc'],
    ['high', 'high', '4', '4', 'med', 'med', 'acc'],
    ['low', 'low', '2', '4', 'small', 'high', 'good'],
    ['low', 'med', '3', '4', 'med', 'high', 'vgood'],
]

# 对测试数据进行相同的标签编码操作, 才可以使用训练好的模型
data = np.array(data).T
test_x, test_y = [], []
for row in range(len(data)):
    encoder = encoders[row]
    if row < len(data) - 1:
        test_x.append(encoder.transform(data[row]))
    else:
        test_y = encoder.transform(data[row])

test_x = np.array(test_x).T

pred_test_y = model.predict(test_x)
e = encoders[-1]
print(e.inverse_transform(test_y))
print(e.inverse_transform(pred_test_y))

验证曲线

验证曲线: 模型性能 = f(超参数)
验证曲线是超参数优选的一种解决方案, 通过验证曲线相关API, 可以得到相同模型在不同超参数下的模型性能得分, 从而得知最优超参数.

import sklearn.model_selection as ms
train_scores, test_scores = ms.validation_curve(
    model,  # 初始模型
    输入集, 输出集,
    'n_estimators', # 超参数名
    np.array([50, 60, 80, 100]), # 超参数取值列表
    cv=5, # 折叠�树
)

train scores的结构

超参数 CV1 CV2 CV3 CV4
50 0.973 0.894 0.944 0.924
100 0.914 0.924 0.934 0.954

test_scores的结构与上述结构一致.

案例: 小汽车案例中使用验证曲线选择超参数.

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 = np.loadtxt('./car.txt', delimiter=',', dtype='U10')
#
# data = data.T
# encoders = []
# train_x, train_y = [], []
#
# 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
# # 基于随机森林分类器完成模型训练
# model = se.RandomForestClassifier(max_depth=6, random_state=7)
#
# # 获取关于n_estimators的验证曲线
# n_estimators = np.arange(50, 550, 50)
# train_scores, test_scores = ms.validation_curve(
#     model, train_x, train_y,
#     'n_estimators', n_estimators, cv=5
# )
#
# train_means = train_scores.mean(axis=1)
# for p, s in zip(n_estimators, train_means):
#     print(p, '->', s)
#
# mp.figure('N_estimators', facecolor='lightgray')
# mp.title('N_estimators', fontsize=16)
# mp.xlabel('Estimators', fontsize=14)
# mp.ylabel('Scores', fontsize=14)
# mp.tick_params(labelsize=12)
# mp.grid(linestyle=":")
# mp.plot(n_estimators, train_means, c='dodgerblue', label='Valid Curve')
# mp.legend()
# mp.show()

data = np.loadtxt('./car.txt', delimiter=',', dtype='U10')

data = data.T
encoders = []
train_x, train_y = [], []

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
# 基于随机森林分类器完成模型训练
model = se.RandomForestClassifier(max_depth=8, n_estimators=200, random_state=7)

# 获取关于n_estimators的验证曲线
max_depths = np.arange(1, 11)
train_scores, test_scores = ms.validation_curve(
    model, train_x, train_y,
    'max_depth', max_depths, cv=5
)

train_means = train_scores.mean(axis=1)
for p, s in zip(max_depths, train_means):
    print(p, '->', s)

mp.figure('max_depths', facecolor='lightgray')
mp.title('max_depths', fontsize=16)
mp.xlabel('max_depth', fontsize=14)
mp.ylabel('Scores', fontsize=14)
mp.tick_params(labelsize=12)
mp.grid(linestyle=":")
mp.plot(max_depths, train_means, c='dodgerblue', label='Valid Curve')
mp.legend()
mp.show()

print(ms.cross_val_score(model, train_x, train_y, cv=4, scoring='f1_weighted').mean())
model.fit(train_x, train_y)
# 造一些测试数据, 进行测试
data = [
    ['high', 'med', '5more', '4', 'big', 'low', 'unacc'],
    ['high', 'high', '4', '4', 'med', 'med', 'acc'],
    ['low', 'low', '2', '4', 'small', 'high', 'good'],
    ['low', 'med', '3', '4', 'med', 'high', 'vgood'],
]

# 对测试数据进行相同的标签编码操作, 才可以使用训练好的模型
data = np.array(data).T
test_x, test_y = [], []
for row in range(len(data)):
    encoder = encoders[row]
    if row < len(data) - 1:
        test_x.append(encoder.transform(data[row]))
    else:
        test_y = encoder.transform(data[row])

test_x = np.array(test_x).T

pred_test_y = model.predict(test_x)
e = encoders[-1]
print(e.inverse_transform(test_y))
print(e.inverse_transform(pred_test_y))

学习曲线

学习曲线:模型性能 = f(训练集大小)

学习曲线相关API:

import sklearn.model_selection as ms
# 获取学习曲线
_, train_scores, test_scores = ms.learning_curve(
    model, # 初始模型
    输入集, 输出集,
    [0.9, 0.8, 0.7], # 训练集大小
    cv=5 # 折叠数
)

案例:

data = np.loadtxt('./car.txt', delimiter=',', dtype='U10')

data = data.T
encoders = []
train_x, train_y = [], []

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
# 基于随机森林分类器完成模型训练
model = se.RandomForestClassifier(max_depth=8, n_estimators=200, random_state=7)

# 使用学习曲线获取最优训练集大小
train_sizes = np.linspace(0.1, 1, 10)
_, train_scores, test_scores = ms.learning_curve(
    model, train_x, train_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')
mp.title('Learning Curve', fontsize=16)
mp.xlabel('Train Size', fontsize=12)
mp.ylabel('Curve Score', fontsize=12)
mp.tick_params(labelsize=10)
mp.grid(linestyle=':')
mp.plot(train_sizes, train_means, 'o-', c='dodgerblue', label='Curve')
mp.legend()
mp.show()

支持向量机(SVM)

核心理念: 寻求最优分类边界
正确: 对大部分样本可以正确的划分类别.
泛化: 最大化支持向量间距.
公平: 类别与支持向量等距.
简单: 线性, 直线, 平面做类别分割.
基于核函数的升维变换
基于难以分类的一些样本, 执行基于核函数的升维变换. 增加新的特征, 使得低维度空间的线性不可分问题, 变成高维度空间中的线性可分问题.
SVM提供的常用核函数

  1. 线性核函数 linear
  2. 多项式核函数 poly
  3. 径向核函数 rbf
    线性核函数
    不通过核函数进行维度提升, 仅在原始维度空间中寻求线性分类便捷.
    基于线性核函数的SVM分类器:
import  sklearn.svm as svm
model = svm.SVC(kernel='linear')
model.fit(train_x, train_y)

案例: 使用线性核函数的SVM训练multiple2.txt

import numpy as np
import sklearn.model_selection as ms
import sklearn.svm as svm
import sklearn.metrics as sm
import matplotlib.pyplot as mp

x, y = [], []
data = np.loadtxt('multiple2.txt', delimiter=',', dtype='f8')
x = data[:, :-1]
y = data[:, -1]

train_x, test_x, train_y, test_y = ms.train_test_split(x, y, test_size=0.25, random_state=5)

# 基于线性核函数的支持向量机模型
model = svm.SVC(kernel='linear')
model.fit(train_x, train_y)

# 画出分类边界
n = 500
l, r = x[:, 0].min() - 1, x[:, 0].max() + 1
b, t = x[:, 1].min() - 1, x[:, 1].max() + 1
grid_x, grid_y = np.meshgrid(
    np.linspace(l, r, n),
    np.linspace(l, r, n)
)
samples = np.column_stack(
    (grid_x.ravel(), grid_y.ravel())
)
grid_z = model.predict(samples)
grid_z = grid_z.reshape(grid_x.shape)
# 使用模型预测测试集数据, 输出分类报告
pred_test_y = model.predict(test_x)
cr = sm.classification_report(test_y, pred_test_y)
print(cr)

# 绘制分类边界
mp.figure('SVM Linear Classfication', facecolor='lightgray')
mp.title('SVM Linear Classfication', fontsize=16)
mp.xlabel('x', fontsize=14)
mp.ylabel('y', fontsize=14)
mp.tick_params(labelsize=12)
mp.pcolormesh(grid_x, grid_y, grid_z, cmap='gray')
mp.scatter(train_x[:, 0], train_x[:, 1], c=train_y, cmap='brg', s=80)
mp.show()

多项式核函数
通过多项式函数增加原始样本特征的高次幂作为新的特征, 在新的思考维度中对样本进行分类.

# 基于多项式核函数扩展新的特征
model = svm.SVC(kernel='poly', degree=3)
model.fit(train_x, train_y)

径向基核函数

通过高斯分布函数增加原始样本特征的分布概率

# 基于径向基核函数扩展新的特征
# C: 正则强度, 过拟合调大
# gamma: 正太分布曲线的标准差
model = svm.SVC(kernel='rbf', C=600, gamma=0.01)
model.fit(train_x, train_y)

样本类别均衡化

通过类别均衡化, 使所占比例较小的样本权重较高, 而所占比例较大的样本权重较低. 平均化不同类别样本对分类模型的贡献, 以提高模型精度.

# 添加class_weight = 'balanced' 实现样本类别均衡化
model = svm.SVC(kernel='linear', class_weight='balanced')
model.fit(train_x, train_y)

案例: 基于线性核函数对imbalance.txt进行训练

# 基于线性核函数的支持向量机模型
model = svm.SVC(kernel='rbf', C=1000,
                gamma=0.01,
                class_weight='balanced')
model.fit(train_x, train_y)

置信概率

根据样本与分类边界的距离远近, 对其预测类别的可信程度进行量化, 离边界越近的样本, 置信概率越低, 反之, 离边界越远的样本, 置信概率越高.

获取每个样本的置信概率API:

# 在获取支持向量机模型时, 给出超参数 probability = True
# 获取每个样本的置信概率
置信概率矩阵 = model.predict_proba(test_x)
m = svm.SVC(kelnel='', C=1, gamma=0.01, probability=True)

置信概率矩阵格式:

- 类别1 类别2
样本1 0.8 0.2
样本2 0.6 0.4

案例: 修改径向基核函数的SVM案例, 新增测试样本, 输出置信概率.

# 新增测试点 输出置信概率, 绘制图像
prob_x = np.array([
    [2, 1.5],
    [8, 9],
    [4.8, 5.2],
    [4, 4],
    [2.5, 7],
    [7.6, 2],
    [5.4, 5.9],
])
pred_prob_y = model.predict(prob_x)
probs = model.predict_proba(prob_x)
print(probs)

mp.scatter(prob_x[:, 0], prob_x[:, 1], c=pred_prob_y, cmap='jet_r', s=80, marker='D')

# 为每个点加上备注: 1类别概率, 2类别概率
for i in range(len(probs)):
    mp.annotate(
        '{}% {}%'.format(
            round(probs[i, 0]*100, 2),
            round(probs[i, 1]*100, 2),
        ),
        xy=(prob_x[i, 0], prob_x[i, 1]),
        xytext=(12, -12),
        textcoords='offset points',
        fontsize=9,
        bbox={
            'boxstyle': 'round, pad=0.6',
            'fc': 'orange',
            'alpha': 0.8
            }
    )

网格搜索

获取一个最优超参数的方式可以绘制验证曲线, 但是验证曲线只能每次获取一个最优超参数. 如果多个超参数有很多排列组合的话, 就可以使用网格搜索寻求最优超参数组合.

在网格搜索过程中, 针对每一个超参数组合, 实例化给定的模型, 做cv次交叉验证, 将其中平均f1得分最高的超参数组合作为最佳选择, 实例化模型对象.(FlyAI)

网格搜索相关API:

import sklearn.model_selection as ms
# 返回的是已经使用了最优超参数组合的model对象
model = ms.GridSearchCV(
    model,              # 原始模型
    超参数组合列表,     # 使用列表的方式把所有组合列出
    cv=5                # 交叉验证折叠树
)
# 获取网格搜索过程中每个参数的组合
model.cv_results_['params']
# 获取网格搜索中每个参数组合对应的平均测试分
model.cv_results_['mean_test_score']
# 获取最好的参数
model.best_params_  # 最优参数
model.best_scores_  # 最优得分
model.best_estimator_   # 最优模型

案例: 修改置信概率案例, 基于网格搜索寻求最优超参数

# 基于径向基核函数的支持向量机模型
model = svm.SVC()
# 整理超参数列表, 做网格搜索, 寻找最优
params = [
    {
    'kernel': ['linear'],
    'C': [1, 10, 100, 1000]
    },
    {
    'kernel': ['poly'],
    'C': [1],
    'degree': [2, 3]
    },
    {
    'kernel': ['rbf'],
    'C': [1, 10, 100, 1000],
    'gamma': [1, 0.1, 0.01, 0.001]
    }
]
model = ms.GridSearchCV(model, params, cv=5)
model.fit(train_x, train_y)
print(model.best_params_)
print(model.best_score_)
print(model.best_estimator_)

# 查看网格搜索过程的细节
for p, s in zip(
    model.cv_results_['params'],
    model.cv_results_['mean_test_score']
):
    print(p, '->', s)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章