Python&logstic回归:用户流失预测
对于同一批玩家,从玩家从应用商店点击下载按钮开始,就正式开始了游戏的体验环节,纵观玩家的游戏生命周期,同一批玩家会从留存数据上表现出普适性的行为,如下图:
而对于不同阶段,对玩家进行分析的侧重点又是有所区别的,比如在玩家留存震荡期,重点关注未留存玩家,这时主要关注游戏前期体验各环节(未进入游戏前,进入游戏后)的转化率;
在留存淘汰期,主要关注游戏App仍保留在玩家手机桌面上却活跃度降低的沉默玩家,加以沉默唤醒的运营手段;在留存稳定期,对目标玩家群体则要重点关注刚性流失因素所导致的玩家流失。
常见的游戏运营手段在稳定期用户流失情况的挽留显得并不有效,刚性流失的原因显得错综复杂,另一方面,导入一个新用户的成本显然高于维护一个老玩家,此时,运营或者策划人员会对已流失玩家的构成及行为作分析,总结其流失原因,微调产品或者做运营挽留(死亡推送等)。但是事后总结的方式,风险高效益低。如果能提前预测流失用户,针对预测出的流失风险高的玩家做相应的挽留,这样明显效率倍升。在gamedatas网站上讲过一篇利用近邻的方式做流失预测 《Python&kNN近邻:玩家流失预测》 ,对于符合业务逻辑的异常值普遍存在的游戏数据而言,K近邻的方式存在对异常值不敏感的缺点,本文作者讲介绍另外一种机器学习的算法(logistic回归)来作流失预测。算法主要用python实现,如有问题,可以加入GameDatas官方QQ群:90342017,与Fish交流。
那何为logistic模型呢?logistic模型属于概率型非线性回归,它是研究二分类观察结果与一些影响因素之间关系的一种多变量分析方法。在流行病学研究中,经常需要分析疾病与各危险因素之间的定量关系,为了正确说明这种关系,需要排除一些混杂因素的影响。传统上常常使用Mantel-Haenszel分层分析方法,但这一方法适用于样本含量大,分析因素较少的情况。如果用线性回归分析,由于应变量Y是一个二值变量(通常取值1或0),不满足应用条件,尤其当各因素都处于低水平或高水平时,预测值Y值可能超出0~1范围,出现不合理都现象。用logisitic回归分析则可以较好的解决上述问题。(源自百度百科)
logistic算法步骤:
1.挑选影响玩家流失的主要影响因素,根据Fish的工作经验及业务理解,Fish选取了流失用户特征,登陆天数频次,是否充值,等级流失概率,最后登陆时间,玩家重复行为等。
2.利用梯度上升方法对模型参数进行估计
3.检验模型训练结果
具体Python代码如下:
#!usr/bin/python
__createTime__
=
'20150615'
__author__
=
'fish.huang'
import
numpy as np
def
sigmoid(inX):
'''
sigmoid函数计算流失概率
'''
return
1.0
/
(
1
-
np.exp(
-
inX))
def
stocGradAscent(dataMatrix,classLabels,numIter):
'''
:param dataMatrix:输入数据矩阵
:param classLabels:数据标签,1-流失玩家;0-留存玩家
:param numIter:
:return:返回梯度上升法估计的模型参数
'''
numIter
=
150
m,n
=
np.shape(dataMatrix)
weights
=
np.ones(n)
for
j
in
range
(numIter):
dataIndex
=
range
(m)
for
i
in
range
(m):
alpha
=
4
/
(
1.0
+
j
+
i)
+
0.01
randIndex
=
int
(np.random.uniform(
0
,
len
(dataIndex)))
h
=
sigmoid(
sum
(dataMatrix[randIndex]
*
weights))
error
=
classLabels[randIndex]
-
h
weights
=
weights
+
alpha
*
error
*
dataMatrix[randIndex]
del
(dataIndex[randIndex])
return
weights
def
classifyVector(inX,weights):
'''
根据logistic模型算出的概率对玩家进行分类,概率大于0.5属于流失玩家,概率小于0.5属于留存玩家
'''
prob
=
sigmoid(
sum
(inX
*
weights))
if
prob >
0.5
:
return
1.0
else
:
return
0.0
def
logisticTest ():
'''
数据处理,并进行logistic参数估计,然后利用分类器分类,计算错误率
'''
frTrain
=
open
(
'train.txt'
)
frTest
=
open
(
'test.txt'
)
trainingSet
=
[]
trainingLabel
=
[]
for
line
in
frTrain.readlines():
currLine
=
line.strip().split(
'/t'
)
lineArr
=
[]
for
i
in
range
(
21
):
lineArr.append(
float
(currLine[i]))
trainingSet.append(lineArr)
trainingLabel.append(
float
(currLine[
21
]))
trainWeights
=
stocGradAscent(np.array(trainingSet),trainingLabel,
500
)
errorCount
=
0
numTestVec
=
0.0
for
line
in
frTest.readlines():
numTestVec
+
=
1.0
currLine
=
line.strip().split(
'/t'
)
lineArr
=
[]
for
i
in
range
(
21
):
lineArr.append(
float
(currLine[i]))
if
int
(classifyVector(np.array(lineArr),trainWeights)) !
=
int
(currLine[
21
]):
errorCount
+
=
1
errorRate
=
(
float
(errorCount)
/
numTestVec)
print
"the error rate of this test is : %f "
%
errorRate
return
errorRate
def
multiTest():
'''
多次训练检验,计算平均错误率
'''
numTests
=
10
errorSum
=
0.0
for
k
in
range
(numTests):
errorSum
+
=
colicTets()
print
"after %d iterations the average error rate is : %f "
%
(numTests,errorSum
/
float
(numTests))
结果:
the error rate of this test is : 6.12%
the error rate of this test is :7.32%
the error rate of this test is :6.33%
...
...
...
after 50 iterations the average error rate is : 6.08%
有结果可知,每次计算的判断错误率在6%左右,经过50次计算之后平均错误率在6.08%左右,效果明显很好,可用于实际工作中的流失预测。
作者:fish
2016-3-3 13:39
博士
文章: 822 篇 浏览: 27034 次
微信扫描二维码关注
互联网分析沙龙微信号