KNN算法在保险业精准营销中的应用

一、KNN算法概述

KNN是Machine Learning领域一个简单又实用的算法,与之前讨论过的算法主要存在两点不同:

  1. 它是一种非参方法。即不必像线性回归、逻辑回归等算法一样有固定格式的模型,也不需要去拟合参数。
  2. 它既可用于分类,又可应用于回归。

KNN的基本思想有点类似“物以类聚,人以群分”,打个通俗的比方就是“如果你要了解一个人,可以从他最亲近的几个朋友去推测他是什么样的人”。

在分类领域,对于一个未知点,选取K个距离(可以是欧氏距离,也可以是其他相似度度量指标)最近的点,然后统计这K个点,在这K个点中频数最多的那一类就作为分类结果。比如下图,若令K=4,则?处应分成红色三角形;若令K=6,则?处应分类蓝色正方形。

在回归(简单起见,这里讨论一元回归)领域,如果只知道某点的预测变量$x$,要回归响应变量$y$,只需要在横坐标轴上(因为不知道纵坐标的值,所以没法计算欧氏距离)选取K个最近的点,然后平均(也可以加权平均)这些点的响应值,作为该点的响应值即可。比如下图中,已知前5个点的横纵坐标值,求$x=6.5$时,$y$为多少?若令K=2,则距6.5最近的2个点是(5.1, 8)和(4, 27),把这两个点的纵坐标平均值17.5就可以当作回归结果,认为$x=6.5时,y=17.5。$

KNN具体的算法步骤可参考延伸阅读文献1。

二、KNN性能讨论

KNN的基本思想与计算过程很简单,你只需要考虑两件事:

  1. K预设值取多少?
  2. 如何定义距离?

其中如何定义距离这个需要结合具体的业务应用背景,本文不细致讨论,距离计算方法可参看延伸阅读文献2。这里只讨论K取值时对算法性能的影响。

在上图中,紫色虚线是贝叶斯决策边界线,也是最理想的分类边界,黑色实线是KNN的分类边界。

可以发现:K越小,分类边界曲线越光滑,偏差越小,方差越大;K越大,分类边界曲线越平坦,偏差越大,方差越小。

所以即使简单如KNN,同样要考虑偏差和方差的权衡问题,表现为K的选取。

KNN的优点就是简单直观,无需拟合参数,在样本本身区分度较高的时候效果会很不错;但缺点是当样本量大的时候,找出K个最邻近点的计算代价会很大,会导致算法很慢,此外KNN的可解释性较差。

KNN的一些其他问题的思考可参看延伸阅读文献3。

三、实战案例

1、KNN在保险业中挖掘潜在用户的应用

这里应用ISLR包里的Caravan数据集,先大致浏览一下:

> library(ISLR)
> str(Caravan)
'data.frame':   5822 obs. of  86 variables:
 $ Purchase: Factor w/ 2 levels "No","Yes": 1 1 1 1 1 1 1 1 1 1 ...
> table(Caravan$Purchase)/sum(as.numeric(table(Caravan$Purchase)))
        No        Yes 
0.94022673 0.05977327 

5822行观测,86个变量,其中只有Purchase是分类型变量,其他全是数值型变量。Purchase两个水平,NoYes分别表示不买或买保险。可见到有约6%的人买了保险。

由于KNN算法要计算距离,这85个数值型变量量纲不同,相同两个点在不同特征变量上的距离差值可能非常大。因此要归一化,这是Machine Learning的常识。这里直接用scale()函数将各连续型变量进行正态标准化,即转化为服从均值为0,标准差为1的正态分布。

> standardized.X=scale(Caravan[,-86])
> mean(standardized.X[,sample(1:85,1)])
[1] -2.047306e-18
> var(standardized.X[,sample(1:85,1)])
[1] 1
> mean(standardized.X[,sample(1:85,1)])
[1] 1.182732e-17
> var(standardized.X[,sample(1:85,1)])
[1] 1
> mean(standardized.X[,sample(1:85,1)])
[1] -3.331466e-17
> var(standardized.X[,sample(1:85,1)])
[1] 1

可见随机抽取一个标准化后的变量,基本都是均值约为0,标准差为1。

> #前1000观测作为测试集,其他当训练集
> test <- 1:1000
> train.X <- standardized.X[-test,]
> test.X <- standardized.X[test,]
> train.Y <- Caravan$Purchase[-test]
> test.Y <- Caravan$Purchase[test]
> knn.pred <- knn(train.X,test.X,train.Y,k=)
> mean(test.Y!=knn.pred)
[1] 0.117
> mean(test.Y!="No")
[1] 0.059

当K=1时,KNN总体的分类结果在测试集上的错误率约为12%。由于大部分的人都不买保险(先验概率只有6%),那么如果模型预测不买保险的准确率应当很高,纠结于预测不买保险实际上却买保险的样本没有意义,同样的也不必考虑整体的准确率(Accuracy)。作为保险销售人员,只需要关心在模型预测下会买保险的人中有多少真正会买保险,这是精准营销的精确度(Precision);因此,在这样的业务背景中,应该着重分析模型的Precesion,而不是Accuracy。

> table(knn.pred,test.Y)
        test.Y
knn.pred  No Yes
     No  874  50
     Yes  67   9
> 9/(67+9)
[1] 0.1184211

可见K=1时,KNN模型的Precision约为12%,是随机猜测概率(6%)的两倍!

下面尝试K取不同的值:

> knn.pred <- knn(train.X,test.X,train.Y,k=3)
> table(knn.pred,test.Y)[2,2]/rowSums(table(knn.pred,test.Y))[2]
Yes 
0.2 
> knn.pred <- knn(train.X,test.X,train.Y,k=5)
> table(knn.pred,test.Y)[2,2]/rowSums(table(knn.pred,test.Y))[2]
      Yes 
0.2666667 

可以发现当K=3时,Precision=20%;当K=5时,Precision=26.7%。

作为对比,这个案例再用逻辑回归做一次!

> glm.fit <- glm(Purchase~.,data=Caravan,family = binomial,subset = -test)
Warning message:
glm.fit:拟合機率算出来是数值零或一 
> glm.probs <- predict(glm.fit,Caravan[test,],type = "response")
> glm.pred <- ifelse(glm.probs >0.5,"Yes","No")
> table(glm.pred,test.Y)
        test.Y
glm.pred  No Yes
     No  934  59
     Yes   7   0

这个分类效果就差很多,Precision竟然是0!事实上,分类概率阈值为0.5是针对等可能事件,但买不买保险显然不是等可能事件,把阈值降低到0.25再看看:

> glm.pred <- ifelse(glm.probs >0.25,"Yes","No")
> table(glm.pred,test.Y)
        test.Y
glm.pred  No Yes
     No  919  48
     Yes  22  11

这下子Precision就达到1/3了,比随机猜测的精确度高出5倍不止!

以上试验都充分表明,通过机器学习算法进行精准营销的精确度比随机猜测的效果要强好几倍!

2、KNN回归

在R中,KNN分类函数是knn(),KNN回归函数是knnreg()

> #加载数据集BloodBrain,用到向量logBBB和数据框bbbDescr
> library(caret)
> data(BloodBrain)
> class(logBBB)
[1] "numeric"
> dim(bbbDescr)
[1] 208 134
> #取约80%的观测作训练集。
> inTrain <- createDataPartition(logBBB, p = .8)[[1]]
> trainX <- bbbDescr[inTrain,] 
> trainY <- logBBB[inTrain]
> testX <- bbbDescr[-inTrain,]
> testY <- logBBB[-inTrain]
> #构建KNN回归模型
> fit <- knnreg(trainX, trainY, k = 3) 
> fit
3-nearest neighbor regression model
> #KNN回归模型预测测试集
> pred <- predict(fit, testX)
> #计算回归模型的MSE
> mean((pred-testY)^2)
[1] 0.5821147

这个KNN回归模型的MSE只有0.58,可见回归效果很不错,偏差很小!下面用可视化图形比较一下结果。

> #将训练集、测试集和预测值结果集中比较
> df <-data.frame(class=c(rep("trainY",length(trainY)),rep("testY",length(testY)),rep("predY",length(pred))),Yval=c(trainY,testY,pred))
> ggplot(data=df,mapping = aes(x=Yval,fill=class))+
+   geom_dotplot(alpha=0.8)

这是dotplot,横坐标才是响应变量的值,纵坐标表频率。比较相邻的红色点和绿色点在横轴上的差异,即表明测试集中预测值与实际值的差距。

> #比较测试集的预测值和实际值
> df2 <- data.frame(testY,pred)
> ggplot(data=df2,mapping = aes(x=testY,y=pred))+
+   geom_point(color="steelblue",size=3)+
+   geom_abline(slope = 1,size=1.5,linetype=2)

这张散点图则直接将测试集中的实际值和预测值进行对比,虚线是$y=x$。点离这条虚线越近,表明预测值和实际值之间的差异就越小。

参考文献

Gareth James et al. <u>An Introduction to Statistical Learning</u>.

Wikipedia. k-nearest neighbors algorithm.

KNN for Smoothing and Prediction.

R中实现knn算法(初学)

延伸阅读

  1. xlm289348, kNN(K-Nearest Neighbor)最邻近规则分类

  2. sanqima, KNN算法中常用的距离计算公式

  3. jmydream, http://blog.csdn.net/jmydream/article/details/8644004

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,158评论 4 370
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,600评论 1 307
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 111,785评论 0 254
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,655评论 0 220
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,075评论 3 295
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,002评论 1 225
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,146评论 2 318
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,918评论 0 211
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,671评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,838评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,318评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,636评论 3 263
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,343评论 3 244
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,187评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,982评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,126评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,934评论 2 279

推荐阅读更多精彩内容