目录
一、常用排序算法
二、正负样本不平衡处理方法总结
三、过拟合和欠拟合
1、过拟合
2、欠拟合
四、向量的相似度计算常用方法
五、模型参数和超参数
六、模型评价
1、准确率Accuracy、查准率(精确率)precision、查全率(召回率)recall、F1:
2、ROC与AUC
3、KS(洛伦兹曲线)评分
原始数据中经常存在正负样本不均衡,比如正负样本的数据比例为100:1.
常用的解决办法有:
1、采样
采样方法是通过对训练集进行处理使其从不平衡的数据集变成平衡的数据集,在大部分情况下会对最终的结果带来提升。
采样分为上采样(Over-sampling)和下采样(Under-sampling),上采样是把小众类复制多份,下采样是从大众类中剔除一些样本,或者说只从大众类中选取部分样本。
缺点:
上采样后的数据集中会反复出现一些样本,训练出来的模型会有一定的过拟合;而下采样的缺点显而易见,那就是最终的训练集丢失了数据,模型只学到了总体模式的一部分。
解决办法:
(1)对于上采样,每次生成新数据点时加入轻微的随机扰动,经验表明这种做法非常有效。
(2)对于下采样,第一种方法叫做EasyEnsemble,利用模型融合的方法(Ensemble):多次下采样(放回采样,这样产生的训练集才相互独立)产生多个不同的训练集,进而训练多个不同的分类器,通过组合多个分类器的结果得到最终的结果。第二种方法叫做BalanceCascade,利用增量训练的思想(Boosting):先通过一次下采样产生训练集,训练一个分类器,对于那些分类正确的大众样本不放回,然后对这个更小的大众样本下采样产生训练集,训练第二个分类器,以此类推,最终组合所有分类器的结果得到最终结果。第三种方法是利用KNN试图挑选那些最具代表性的大众样本,叫做NearMiss,这类方法计算量很大。
2、样本合成 Synthetic Sample
合成样本是为了增加样本数目较少的那一类样本,合成指的是通过组合以有的样本的各个feature从而产生新的样本。
一种简单的方法是从各个feature中随机算出一个已有值,然后拼接成一个新样本,这种方法增加了样本数目较少的那一类样本的数目,作用与上采样方法类似,不同点在于上采样是纯粹的复制样本,而合成样本是随机选取拼接得到新的样本。具有代表性的方法 是SMOTE.
3、改变样本的权重
改变样本权重指的是增大样本数较少类别的样本的权重,当类别较少的样本被误分时,其损失值要乘以相应的权重,从而让分类器更加关注这一类数据较少的样本。
4、一分类
对于正负样本极不平衡的场景,我们可以换一个完全不同的角度来看待问题:把它看做一分类(One Class Learning)或异常检测(Novelty Detection)问题。这类方法的重点不在于捕捉类间的差别,而是为其中一类进行建模,经典的工作包括One-class SVM等。
过拟合是模型在训练集上的表现很好,在测试集上的变现却很差。出现这种现象的主要原因是训练数据集中存在噪音、训练数据太少、特征选择的过多导致模型复杂度高、模型拟合了数据中噪声和训练样例中没有代表性的特征。
(1)、Early stopping
Early stopping便是一种迭代次数截断的方法来防止过拟合的方法,即在模型对训练数据集迭代收敛之前停止迭代来防止过拟合。对模型进行训练的过程即是对模型的参数进行学习更新的过程,这个参数学习的过程往往会用到一些迭代方法,如梯度下降(Gradient descent)学习算法。这样可以有效阻止过拟合的发生,因为过拟合本质上就是对自身特点过度地学习。
(2)、正则化
指的是在目标函数后面添加一个正则化项,一般有L1正则化与L2正则化。L1正则是基于L1范数,即在目标函数后面加上参数的L1范数和项,即参数绝对值和与参数的积项。
L2正则是基于L2范数,即在目标函数后面加上参数的L2范数和项,即参数的平方和与参数的积项。
为解决过拟合,尽量减小高次项特征的影响。使得w的每个元素都很小,接近于0.越小的元素说明越简单,越简单的模型则越不容易过拟合。
L2正则化的公式非常简单,直接在原来的损失函数基础上加上权重参数的平方和。
正则化的目的是限制参数过多或者过大,避免模型更加复杂。例如,使用多项式模型,如果使用10阶多项式,模型可能过于复杂,容易发生过拟合。所以为了防止过拟合,可以将其高阶部分的权重w限制为0,这样就相当于从高阶的形式转化为低阶。为了达到这一目的,最直观的方法是限制w 的个数,但这类是NP难问题,求解非常困难,所以一般的做法是寻找宽松的限定条件:,即所有权重的平方和不超过参数C。这时候我们的目标就转换为:最小化训练样本的误差,但是要遵循w平方和小于C的条件。
L1正则与L2正则区别:
L1:计算绝对值之和,用以产生稀疏性(使参数矩阵中大部分元素变为0),因为它是L0范式的一个最优凸近似,容易优化求解;广泛的用于特征选择机制
L2:计算平方和再开根号,L2范数更多是防止过拟合,并且让优化求解变得稳定快速;L2的目标是衰减权重,使权重更加接近原点1.
所以对于防止过拟合优先使用L2 是比较好的选择。
(3)、数据集扩增
通俗得讲,数据集扩增即需要得到更多的符合要求的数据,即和已有的数据是独立同分布的,或者近似独立同分布的。一般有以下方法:从数据源头采集更多数据、复制原有数据并加上随机噪声、重采样、根据当前数据集估计数据分布参数,使用该分布产生更多数据等。
(4)、dropout
对于神经网络,在训练开始时,随机删除一些(可以设定为一半,也可以为1/3,1/4等)隐藏层神经元,即认为这些神经元不存在,同时保持输入层与输出层神经元的个数不变。这样一次迭代更新便完成了。下一次迭代中,同样随机删除一些神经元,与上次不一样,做随机选择。这样一直进行瑕疵,直至训练结束。
(5)、特征选择,消除关联性大的特征。
在数据分析和数据挖掘以及搜索引擎、个性化推荐等场景中,我们经常需要知道个体间差异的大小,进而评价个体的相似性和类别。常见的比如数据分析中的相关分析,数据挖掘中的分类聚类(K-Means等)算法,搜索引擎进行物品推荐时。
相似度就是比较两个事物的相似性。一般通过计算事物的特征之间的距离,如果距离小,那么相似度大;如果距离大,那么相似度小。
常用的计算相似性的方法有:
1、欧几里得距离(Eucledian Distance)
欧氏距离是最常用的距离计算公式,衡量的是多维空间中各个点之间的绝对距离,当数据很稠密并且连续时,这是一种很好的计算方式。
因为计算是基于各维度特征的绝对数值,所以欧氏度量需要保证各维度指标在相同的刻度级别,比如对身高(cm)和体重(kg)两个单位不同的指标使用欧式距离可能使结果失效。
from math import *
def Eucledian(x,y):
return sqrt(sum(pow(a-b,2) for a, b in zip(x,y)))
2、曼哈顿距离(Manhattan Distance)
曼哈顿距离的实现同欧氏距离类似,都是用于多维数据空间距离的度量。距离越小,相似度越大。
def Manhattan(x,y):
return sum(abs(a - b) for a, b in zip(x,y))
3、明可夫斯基距离(Minkowski distance)
明氏距离是欧氏距离的推广,是对多个距离度量公式的概括性的表述。
从公式我们可以看出,
def Minkowski(x,y,p):
sumValue = sum(pow(abs(a-b),p) for a, b in zip(x,y))
mi = 1/float(p)
return round(sumValue**mi, 3) # 保留3位小数
4、余弦相似度(Cosine Similarity)
余弦相似度用向量空间中两个向量夹角的余弦值作为衡量两个个体间差异的大小。相比距离度量,余弦相似度更加注重两个向量在方向上的差异,而非距离或长度上。
import numpy as np
def cosine(x,y):
num = np.sum(x*y)
denom = np.linalg.norm(x)*np.linalg.norm(y)
return round(num/denom,3)
print(cosine(np.array([3,45,7,2]),np.array([2,53,15,75])))
# output:0.622
5、杰卡德相似度Jaccard Similarity
jaccard系数主要用于计算符号度量或布尔值度量的个体间的相似度,因为个体的特征属性都是由符号度量或者布尔值标识,因此无法衡量差异具体值的大小,只能获得“是否相同”这个结果,所以Jaccard系数只关心个体间共同具有的特征是否一致这个问题。
import numpy as np
def jaccard(x,y):
intersection_cardinality = len(set.intersection(*[set(x),set(y)]))
union_cardinality = len(set.union(*[set(x),set(y)]))
return intersection_cardinality / union_cardinality
print(jaccard([1,2,3,1,2,3],[3,4,5,3,4,5]))
#output:0.2
6、皮尔森相关系数(Pearson Correlation Coefficient)
又称相关相似性,通过Pearson相关系数来度量两个用户的相似性。计算时,首先找到两个用户共同评分过的项目集,然后计算这两个向量的相关系数。一般用于 计算两个定距变量间联系的紧密程度。用来反应两个变量线性相关程度的统计量,取值在[-1,1]之间,绝对值越大,表明相关性越强,负相关对于推荐的意义小。
1、模型参数
模型参数是模型内部的配置变量,可以用数据估计模型参数的值。
模型参数具有以下特征:进行模型预测时需要模型参数;模型参数值可以定义模型功能;模型参数用数据估计或数据学习得到;模型参数一般不由实践者手动设置。
通常使用优化算法估计模型参数,优化算法是对参数的可能值进行的一种有效搜索。
模型参数的一些例子包括:人造神经网络的权重;支持向量机中的支持向量;线性回归或逻辑回归中的系数。
2、模型超参数
模型超参数是模型外部的配置,其值不能从数据估计中得到,必须手动设置参数的值。
具体特征有:模型超参数常应用于估计模型参数的过程中;模型超参数通常由实践者直接指定;模型超参数通常可以使用启发式方法来设置;模型超参数通常根据给定的预测模型问题而调整。
怎么得到最优值:对于给定的问题,我们无法知道模型超参数的最优值,但我们可以使用经验法则来探寻其最优值,或复制用于其他问题的值,也可以通过反复试验的方法。
模型超参数的一些列子包括:训练神经网络的学习率;支持向量机的C和sigma超参数;k邻域中的k。
分类模型评估:
指标 | 描述 | Scikit-learn函数 |
---|---|---|
Precision | 精准度 | from sklearn.metrics import precision_score |
Recall | 召回率 | from sklearn.metrics import recall_score |
F1 | F1值 | from sklearn.metrics import f1_score |
Confusion Matrix | 混淆矩阵 | from sklearn.metrics import confusion_matrix |
ROC | ROC曲线 | from sklearn.metrics import roc |
AUC | ROC曲线下的面积 | from sklearn.metrics import auc |
回归模型评估:
指标 | 描述 | Scikit-learn函数 |
---|---|---|
Mean Square Error (MSE, RMSE) | 平均方差 | from sklearn.metrics import mean_squared_error |
Absolute Error (MAE, RAE) | 绝对误差 | from sklearn.metrics import mean_absolute_error, median_absolute_error |
R-Squared | R平方值 | from sklearn.metrics import r2_score |
查准率是针对我们预测结果而言的,它表示的是预测为正的样本中有多少是对的。那么预测为正就有两种可能了,一种就是把正类预测为正类(TP),另一种就是把负类预测为正类(FP)。
P = TP / (TP + FP)
而召回率是针对我们原来的样本而言的,它表示的是样本中的正例有多少被预测正确了。那也有两种可能,一种是把原来的正类预测成正类(TP),另一种就是把原来的正类预测为负类(FN).
R = TP / (TP + FN)
查准率和查全率是互相影响的,理想情况下是做到两者都高。但是一般情况下查准率高、查全率就低。
如果是做搜索,那就是保证查全率的情况下提升查准率;如果是做疾病监测、反垃圾,则是保证查准率的条件下,提高查全率。两者都要求高的情况下,可以用F1来衡量。
查准率-查全率曲线,即“P-R曲线”,进行比较学习器的性能。若一个学习器的P-R曲线完全被另一个学习器的曲线包住,则可断言后者的性能优于前者(A>C)。当两个曲线发生交叉时,通过“平衡点”(break even point),即查准率 == 查全率时的取值(A>B)。
更常用的是F1度量,基于查准率和查全率的调和平均定义。
F1的一般形式为:
其中β>0度量了查全率对查准率的想对重要性。β = 1时为标准的F1。β>1时查全率有更大影响;β<1时查准率有更大影响。
mport numpy as np
y_true = np.array([0, 1, 1, 0, 1, 0])
y_pred = np.array([1, 1, 1, 0, 0, 1])
# True Positive
TP = np.sum(np.multiply(y_true,y_pred))
print(TP) # output:2
# false positive
FP = np.sum(np.logical_and(np.equal(y_true, 0), np.equal(y_pred, 1))) # 逻辑与
print(FP) # output:2
# false negative
FN = np.sum(np.logical_and(np.equal(y_true, 1), np.equal(y_pred, 0)))
print(FN) # output:1
# true negative
TN = np.sum(np.logical_and(np.equal(y_true, 0), np.equal(y_pred, 0)))
print(TN) #output:1
## sklearn 实现
from sklearn import metrics
y_true = [0, 1, 1, 0, 1, 0]
y_pred = [1, 1, 1, 0, 0, 1]
p = metrics.precision_score(y_true, y_pred, average='binary')
r = metrics.recall_score(y_true, y_pred, average='binary')
f1score = metrics.f1_score(y_true, y_pred, average='binary')
print(p) #output:0.5
print(r) # output:0.67
print(f1score) #output:0.57
## tensorflow 实现
import tensorflow as tf
sess = tf.Session()
y_true = tf.constant([0, 1, 1, 0, 1, 0])
y_pred = tf.constant([1, 1, 1, 0, 0, 1])
# true positive
TP = tf.reduce_sum(tf.multiply(y_true, y_pred))
print(sess.run(TP))
# false positive
FP = tf.reduce_sum(tf.cast(tf.logical_and(tf.equal(y_true, 0), tf.equal(y_pred, 1)), tf.int32))
print(sess.run(FP))
# false negative
FN = tf.reduce_sum(tf.cast(tf.logical_and(tf.equal(y_true, 1), tf.equal(y_pred, 0)), tf.int32))
print(sess.run(FN))
# true negative
TN = tf.reduce_sum(tf.cast(tf.logical_and(tf.equal(y_true, 0), tf.equal(y_pred, 0)), tf.int32))
print(sess.run(TN))
ROC全称是“受试者工作特征”(Receiver Operating Characteristic)曲线,与上节中的P-R曲线相似,我们根据学习器的预测结果进行排序,按此顺序逐个把样本作为正例进行预测,每次计算两个重要量的值,分别以他们为横、纵坐标作图,就得到ROC曲线,与P-R曲线采用查准率、查全率为纵、横轴不同,ROC曲线的纵轴是“真正例率” (True Positive Rate, TPR),横轴是“假正例率”(False Positive Rate, FPR),公式为:
TPR = TP / (TP + FN);
FPR = FP / (FP + TN)
在一个二分类模型中,假设采用逻辑回归分类器,其给出针对每个实例为正类的概率,那么通过设定一个阈值如0.6,概率大于等于0.6的为正类,小于0.6的为负类。对应的就可以算出一组(FPR,TPR),在平面中得到对应坐标点。随着阈值的逐渐减小,越来越多的实例被划分为正类,但是这些正类中同样也掺杂着真正的负实例,即TPR和FPR会同时增大。阈值最大时,对应坐标点为(0,0),阈值最小时,对应坐标点(1,1)。
AUC值是一个概率值,当你随机挑选一个正样本以及一个负样本,当前的分类算法根据计算得到的Score值将这个正样本排在负样本前面的概率就是AUC值。当然,AUC值越大,当前的分类算法越有可能将正样本排在负样本前面,即能够更好的分类。
从AUC判断分类器(预测模型)优劣的标准:
- AUC = 1,是完美分类器,采用这个预测模型时,存在至少一个阈值能得出完美预测。绝大多数预测的场合,不存在完美分类器。
- 0.5 < AUC < 1,优于随机猜测。这个分类器(模型)妥善设定阈值的话,能有预测价值。
- AUC = 0.5,跟随机猜测一样(例:丢铜板),模型没有预测价值。
- AUC < 0.5,比随机猜测还差;但只要总是反预测而行,就优于随机猜测。
PRC与ROC的比较:
AUC是ROC的积分(曲线下面积),是一个数值,一般认为越大越好,数值相对于曲线而言更容易当做调参的参照。
PR曲线会面临一个问题,当需要获得更高recall时,model需要输出更多的样本,precision可能会伴随出现下降/不变/升高,得到的曲线会出现浮动差异(出现锯齿),无法像ROC一样保证单调性。
在正负样本分布得极不均匀(highly skewed datasets)的情况下,PRC比ROC能更有效地反应分类器的好坏。
# 方法一:
def cal_auc(list_one, list_two):
'''计算AUC值'''
positive = []
negative = []
for index in range(len(list_one)):
if list_one[index] == 1:
positive.append(index)
else:
negative.append(index)
SUM = 0
for i in positive:
for j in negative:
if list_two[i] > list_two[j]:
SUM += 1
elif list_two[i] == list_two[j]:
SUM += 0.5
else:
pass
return SUM / (len(positive)*len(negative))
# 方法二:
from sklearn.metrics import roc_auc_score
roc_auc_score(test_result,predict_result))
# 计算坐标点和阈值,大于阈值为类别1,小于阈值为类别0
fpr, tpr, thresholds = metrics.roc_curve(y_true, y_score)
auc = metrics.auc(fpr,tpr) # 计算auc值
KS(Kolmogorov-Smirnov)值越大,表示模型能够将正、负客户区分开的程度越大。KS值的取值范围是[0,1]
通常来讲,KS>0.2即表示模型有较好的预测准确性。
ks求解方法:
ks需要TPR和FPR两个值:真正类率(true positive rate ,TPR), 计算公式为TPR=TP/ (TP+ FN),刻画的是分类器所识别出的 正实例占所有正实例的比例。另外一个是假正类率(false positive rate, FPR),计算公式为FPR= FP / (FP + TN),计算的是分类器错认为正类的负实例占所有负实例的比例。KS=max(TPR-FPR)。其中:
TP:真实为1且预测为1的数目
FN:真实为1且预测为0的数目
FP:真实为0的且预测为1的数目
TN:真实为0的且预测为0的数目
计算步骤:
from sklearn import metrics
def ks(y_predicted, y_true):
label=y_true
#label = y_true.get_label()
fpr,tpr,thres = metrics.roc_curve(label,y_predicted,pos_label=1)
return 'ks',abs(fpr - tpr).max()