【机器学习】机器学习算法整理
机器学习算法整理
K近邻
算法思想
一个样本与数据集中的k个样本最相似, 如果这k个样本中的大多数属于某一个类别, 则该样本也属于这个类别。
K值减小就意味着整体模型变复杂,分的不清楚,就容易发生过拟合。
流程:
1) 计算已知类别数据集中的点与当前点之间的距离
2) 按距离递增次序排序
3) 选取与当前点距离最小的k个点
4) 统计前k个点所在的类别出现的频率
5) 返回前k个点出现频率最高的类别作为当前点的预测分类
优点:
- 简单有效
- 重新训练代价低
- 算法复杂度低
- 适合类域交叉样本
- 适用大样本自动分类
缺点:
- 惰性学习
- 类别分类不标准化
- 输出可解释性不强
- 不均衡性
- 计算量较大
适用场景:
通常最近邻分类器使用于特征与目标类之间的关系为比较复杂的数字类型,或者说二者关系难以理解,但是相似类间特征总是相似。数据要求归一化,统一各个特征的量纲。
例子:
import math
movie_data = {"宝贝当家": [45, 2, 9, "喜剧片"],
"美人鱼": [21, 17, 5, "喜剧片"],
"澳门风云3": [54, 9, 11, "喜剧片"],
"功夫熊猫3": [39, 0, 31, "喜剧片"],
"谍影重重": [5, 2, 57, "动作片"],
"叶问3": [3, 2, 65, "动作片"],
"伦敦陷落": [2, 3, 55, "动作片"],
"我的特工爷爷": [6, 4, 21, "动作片"],
"奔爱": [7, 46, 4, "爱情片"],
"夜孔雀": [9, 39, 8, "爱情片"],
"代理情人": [9, 38, 2, "爱情片"],
"新步步惊心": [8, 34, 17, "爱情片"]}
# 测试样本 唐人街探案": [23, 3, 17, "?片"]
#下面为求与数据集中所有数据的距离代码:
x = [23, 3, 17]
KNN = []
for key, v in movie_data.items():
d = math.sqrt((x[0] - v[0]) ** 2 + (x[1] - v[1]) ** 2 + (x[2] - v[2]) ** 2)
KNN.append([key, round(d, 2)])
# 输出所用电影到 唐人街探案的距离
print(KNN)
#按照距离大小进行递增排序
KNN.sort(key=lambda dis: dis[1])
#选取距离最小的k个样本,这里取k=5;
KNN=KNN[:5]
print(KNN)
#确定前k个样本所在类别出现的频率,并输出出现频率最高的类别
labels = {"喜剧片":0,"动作片":0,"爱情片":0}
for s in KNN:
label = movie_data[s[0]]
labels[label[3]] += 1
labels =sorted(labels.items(),key=lambda l: l[1],reverse=True)
print(labels,labels[0][0],sep='\n')
决策树
决策树(Decision Tree)是一种非参数的有监督学习方法,它能够从一系列有特征和标签的数据中总结出决策规则,并用树状图的结构来呈现这些规则,以解决分类和回归问题。决策树算法容易理解,适用各种数据,在解决各种问题时都有良好表现,尤其是以树模型为核心的各种集成算法,在各个行业和领域都有广泛的应用。
决策树算法的核心是要解决提出的两个问题:
1)如何从数据表中找出最佳节点和最佳分枝?
2)如何让决策树停止生长,防止过拟合?
为了要将表格转化为一棵树,决策树需要找出最佳节点和最佳的分枝方法,对分类树来说,衡量这个“最佳”的指标叫做“不纯度”。通常来说,不纯度越低,决策树对训练集的拟合越好。现在使用的决策树算法在分枝方法上的核心大多是围绕在对某个不纯度相关指标的最优化上。
不纯度基于节点来计算,树中的每个节点都会有一个不纯度,并且子节点的不纯度一定是低于父节点的,也就是说,在同一棵决策树上,叶子节点的不纯度一定是最低的。
Criterion这个参数正是用来决定不纯度的计算方法的。sklearn提供了两种选择:
1)输入”entropy“,使用信息熵(Entropy)
2)输入”gini“,使用基尼系数(Gini Impurity)
其中t代表给定的节点,i代表标签的任意分类, 代表标签分类i在节点t上所占的比例。注意,当使用信息熵时,sklearn实际计算的是基于信息熵的信息增益(Information Gain),即父节点的信息熵和子节点的信息熵之差。
比起基尼系数,信息熵对不纯度更加敏感,对不纯度的惩罚最强。但是在实际使用中,信息熵和基尼系数的效果基本相同。信息熵的计算比基尼系数缓慢一些,因为基尼系数的计算不涉及对数。另外,因为信息熵对不纯度更加敏感,所以信息熵作为指标时,决策树的生长会更加“精细”,因此对于高维数据或者噪音很多的数据,信息熵很容易过拟合,基尼系数在这种情况下效果往往比较好。当然,这不是绝对的。
到这里,决策树的基本流程其实可以简单概括如下:
直到没有更多的特征可用,或整体的不纯度指标已经最优,决策树就会停止生长。
顺便一说,最擅长月亮型数据的是最近邻算法,RBF支持向量机和高斯过程;最擅长环形数据的是最近邻算法和高斯过程;最擅长对半分的数据的是朴素贝叶斯,神经网络和随机森林。
参考文档: 【菜菜的sklearn】01 决策树
评估指标
准确率、精确率、召回率
- True Positive(TP),将正类预测为正类的数量。
- False Negative(FN),将正类预测为负类的数量。
- False Positive(FP),将负类预测为正类的数量。
- True Negative(TN),将负类预测为负类的数量。
数量 | 数量 | |
---|---|---|
P正类(positive) | TP | FN |
N负类(native) | FP | FN |
分类准确率(Accurac)实际上就是正确分类的样本数与总样本数的比例,
代码实现👇
## 1.错误率和精度
precision = np.mean(y_pred == y_true)
error = 1 - precision
print(precision, error)
from sklearn.metrics import accuracy_score
# 返回准确率
precision = accuracy_score(y_true, y_pred, normalize=True)
# 返回正确分类的数量
precision_num = accuracy_score(y_true, y_pred, normalize=False)
print(precision, precision_num)
查全率或召回率(Recall,记为R)在实际为正类的样本中,预测正确的比例。
查准率或精确率(Precision,记为p),在预测为正类的样本中,预测正确的比例。
通常来说,查全率和查准率是负相关关系的。代码实现👇
## 2. 查准率、查全率
from sklearn.metrics import precision_score, recall_score
precision = precision_score(y_true, y_pred)
recall = recall_score(y_true, y_pred)
print(precision, recall)
P-R曲线
将样本按置信度由大到小排序,然后遍历样本,每一次都以当前样本为阈值,之前的属于正例,之后的属于负例。每一个阈值都会得到一组P-R值,全部绘制到图上就是P-R曲线。P-R曲线可以直观的显示学习器在样本总体上的查全率、查准率,如下图所示,随着更多的样本被分为正样本,查全率不断增大,查准率降低。通常,当一个学习器的P-R曲线被另一个学习器的曲线完全包住时,则可断言后者的性能优于前者。例如下图中A的学习期性能优于C。
代码实现👇
## 3. P-R曲线的绘制
from sklearn.metrics import precision_recall_curve
from sklearn.datasets import load_iris
from sklearn.multiclass import OneVsRestClassifier
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
from sklearn.preprocessing import label_binarize
import numpy as np
iris = load_iris()
X = iris.data
y = iris.target
y = label_binarize(y, classes=[0, 1, 2]) # one-hot
n_classes = y.shape[1]
# 添加噪声
np.random.seed(0)
n_samples, n_features = X.shape
X = np.c_[X, np.random.randn(n_samples, 200 * n_features)]
# 训练模型
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.5, random_state=0)
clf = OneVsRestClassifier(SVC(kernel='linear', probability=True, random_state=0))
clf.fit(X_train, y_train)
y_score = clf.fit(X_train, y_train).decision_function(X_test)
# 绘制P-R曲线
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
precision = {}
recall = {}
for i in range(n_classes):
precision[i], recall[i], _ = precision_recall_curve(y_test[:, i], y_score[:, i])
ax.plot(recall[i], precision[i], label='target=%s' % i)
ax.set_xlabel("Recall Score")
ax.set_ylabel("Precision Score")
ax.set_title("P-R")
ax.legend(loc='best')
ax.set_xlim(0, 1.0)
ax.set_ylim(0, 1.0)
ax.grid()
plt.show()
但若曲线发生了交叉,那么需要借助F-Score。
ROC曲线和AUC
ROC曲线全称为受试者工作特征曲线(receiver operating characteristic curve),它是根据一系列不同的分类阈值,以真正类率(True Postive Rate,TPR)为纵坐标,假正类率(False Positive Rate,FPR)为横坐标绘制的曲线。其中,真正类率TPR就是我们前面介绍的查全率R,它在ROC曲线中又可以被称为灵敏度(sensitivity);假正类率(FPR)的计算公式是FPR=FP/(FP+TN),它表示将负类错误的识别为正类的样本占所有负类样本的比例,一般我们记1-FPR为特异性(specificity)。
将不同的模型的ROC曲线绘制在同一张图内,最靠近左上角的那条曲线代表的模型的分类效果最好。
实际任务中,情况很复杂,如果两条ROC曲线发生了交叉,则很难一般性地断言谁优谁劣。因此我们引入AUC,AUC(Area Under Curve)被定义为ROC曲线与下方的坐标轴围成的面积,AUC的范围位于[0,1]之间,AUC越大则模型的分类效果越好,如果AUC小于等于0.5,则该模型是不能用的。通常AUC大于0.85的模型就表现可以了。
目标检测任务中IoU和mAP
目标检测任务中常用的评价指标即各类别平均精度,在了解并计算mAP之前,先看一下IoU也即交并比的基本知识。
IoU
IoU的计算公式如下:
python实现如下,假定我们给出两个矩形框,每个矩形框包含左上和右下坐标或者中心点坐标和宽高尺寸:
## 6. IoU
import numpy as np
def compute_iou(box1, box2, wh=False):
"""
compute the iou of two boxes.
Args:
box1, box2: [xmin, ymin, xmax, ymax] (wh=False) or [xcenter, ycenter, w, h] (wh=True)
wh: the format of coordinate.
Return:
iou: iou of box1 and box2.
"""
if wh == False:
xmin1, ymin1, xmax1, ymax1 = box1
xmin2, ymin2, xmax2, ymax2 = box2
else:
xmin1, ymin1 = int(box1[0] - box1[2] / 2.0), int(box1[1] - box1[3] / 2.0)
xmax1, ymax1 = int(box1[0] + box1[2] / 2.0), int(box1[1] + box1[3] / 2.0)
xmin2, ymin2 = int(box2[0] - box2[2] / 2.0), int(box2[1] - box2[3] / 2.0)
xmax2, ymax2 = int(box2[0] + box2[2] / 2.0), int(box2[1] + box2[3] / 2.0)
## 获取矩形框交集对应的左上和右下的坐标
xx1 = np.max([xmin1, xmin2])
yy1 = np.max([ymin1, ymin2])
xx2 = np.min([xmax1, xmax2])
yy2 = np.min([ymax1, ymax2])
## 计算两个矩形框面积
area1 = (xmax1 - xmin1) * (ymax1 - ymin1)
area2 = (xmax2 - xmin2) * (ymax2 - ymin2)
## 计算交集面积
inter_area = np.max([0, xx2 - xx1]) * np.max([0, yy2 - yy1])
## 计算交并比
IoU = inter_area / (area1 + area2 - inter_area)
return IoU