前面两篇文章介绍了澳大利亚天气数据集的特征工程,将数据处理到了可以建模的程度,本文介绍SVM建模来做天气预测。同时在线性模型基础上,介绍准确率和召回率的平衡调节方法。

代码示例

1、建模和模型评估

from sklearn.svm import SVC
from sklearn.metrics import accuracy_score, recall_score, roc_auc_score

kernels = ['linear', 'poly', 'rbf', 'sigmoid']

for k in kernels:
    clf = SVC(kernel=k, degree=1, gamma='auto').fit(x_train, y_train)
    score = clf.score(x_test, y_test)  #准确率
    # 其他指标
    y_pred = clf.predict(x_test)
    recall = recall_score(y_test, y_pred)  #召回率
    auc = roc_auc_score(y_test, clf.decision_function(x_test))
    print('%s score:%.3f, recall:%.3f, auc:%.3f' % (k, score, recall, auc))
    # linear score:0.831, recall:0.431, auc:0.862
    # poly score:0.834, recall:0.422, auc:0.862
    # rbf score:0.806, recall:0.308, auc:0.826
    # sigmoid score:0.637, recall:0.172, auc:0.437

以上训练结果中,准确率还勉强可以,但recall都不高,而且在特征工程阶段,我们就发现数据存在不均衡的问题。所以下面我们还需要在召回率,准确率,以及两者的平衡方向,继续通过调参来优化模型。 

2、追求更高的recall

要追求更高的recall,就要不惜一切代价判断出少数类,以下我们用class_weight=balanced和固定值,来调节权重。

clf = SVC(kernel=k, degree=1, class_weight='balanced', gamma='auto').fit(x_train, y_train)
# linear score:0.786, recall:0.749, auc:0.861
# poly score:0.794, recall:0.755, auc:0.862
# rbf score:0.793, recall:0.597, auc:0.825
# sigmoid score:0.501, recall:0.376, auc:0.437

# class_weight={1:10} 表示1类别占10份,隐藏了0:1
clf = SVC(kernel=k, degree=1, class_weight={1: 10}, gamma='auto').fit(x_train, y_train)
# linear score:0.636, recall:0.905, auc:0.857
# poly score:0.631, recall:0.910, auc:0.857
# rbf score:0.783, recall:0.575, auc:0.812
# sigmoid score:0.245, recall:1.000, auc:0.437

# 随着class_weight的上升,在线性模型上得到了很高的recall值,但这样调整显然无法得到一个临界值。

3、画ROC曲线

经过前面的尝试,我们发现当前数据集,线性模型的效果最好,所以我们在线性模型的基础上,来画ROC曲线,获得临界阈值。

clf = SVC(kernel='linear', degree=1, class_weight='balanced', gamma='auto').fit(x_train, y_train)

from sklearn.metrics import roc_curve
import matplotlib.pyplot as plt
import numpy as np

fpr, tpr, thresholds = roc_curve(y_test, clf.decision_function(x_test))
area = roc_auc_score(y_test, clf.decision_function(x_test))

# 画ROC曲线
# plt.plot(fpr, tpr, label='ROC curve (area=%.3f)' % area)
# plt.plot([0, 1], [0, 1], c='k', linestyle='--')
# plt.legend()
# plt.show()

4、找平衡点threshold

idx = np.argmax(tpr - fpr)
threshold = thresholds[idx]
# 设定阈值下的预测值
prob = clf.decision_function(x_test)
y_pred_t = (prob >= threshold).astype('int')

# 计算平衡点的准确率和召回率
score = accuracy_score(y_test, y_pred_t)
recall = recall_score(y_test, y_pred_t)

print('score:%.3f, recall:%.3f' % (score, recall))
# score:0.801, recall:0.728

至此,这份数据集经过特征处理后,在SVM模型下的效果已经基本到极限了。 如果还想得到更好的效果,可以继续尝试其他模型,但亲测决策树、随机森林、KNN都未能超过SVM的效果。

另一个优化的方向,就是特征工程,但可能要有一定的专业知识,大家有时间还可以继续探索。

本文为 陈华 原创,欢迎转载,但请注明出处:http://ichenhua.cn/read/291