Pandas高级数据分析快速入门之五——机器学习特征工程篇

Pandas高级数据分析快速入门之一——Python开发环境篇
Pandas高级数据分析快速入门之二——基础篇
Pandas高级数据分析快速入门之三——数据挖掘与统计分析篇
Pandas高级数据分析快速入门之四——数据可视化篇
Pandas高级数据分析快速入门之五——机器学习特征工程篇
Pandas高级数据分析快速入门之六——机器学习预测分析篇

0. Pandas高级数据分析使用机器学习概述

需求解决方案技术方案
时序趋势斜率线性回归算斜率,Scipy.stats.linregress
正常状态聚类数据密度,最多的均值聚类数据密度,SKlearn DBScan
数据相关性相关性分析相关系数,Pearson相关系数
预测两种状态聚类分析聚类,SKlearn KMean
数据可比性归一化、标准化数据标准化,sklearn StandardScaler

1. 线性回归计算斜率和方差

在Python科学计算包Scipy的统计模块stats 中,有 linregress 函数可以做一元线性回归,返回斜率、截距、相关系数、p值和标准误差。

交易间隔天数趋势回归斜率,左侧为典型流失情况, K ∆ t = 2.872 K_{∆t}=2.872 Kt=2.872;右侧为不流失正常情况, K ∆ t = − 2.272 K_{∆t}=-2.272 Kt=2.272
在这里插入图片描述
计算斜率和方差

scipy.stats.linregress(x, y=None)

参数:

  • 输入数据x,y,类数组
    两组测量值。两个数组的长度应该相同。如果只给出了x(y=None),那么它必须是一个二维数组,其中一个维度的长度为2。然后通过沿长度为2的维度拆分数组来找到两组测量值。

返回值:

  • 斜率、截距、相关系数、p值和标准误差。

本文涉及到的交易数据,参照上篇博文[1]描述获取数据集及其DataFrame,此处略。

from scipy import stats

def stats_linear_regression(df):
    user_df = df.loc[df['carduser_id']== 2085603 ].reset_index(drop=True)
       
    Days = user_df['days'].values
    Days = Days[1:]
    k = []
    for i in range(len(Days)):
        k.append(i)
    #Days = Days.reshape(-1,1)
    x = np.array(k)
    y = Days
    # 科学计算包中统计方法,用于计算散点回归线趋势的斜率、截距
    slope, intercept, r_value, p_value, std_err = stats.linregress(x, y) 
    print('slope is ' + str(slope))
    
    # 画图
    plt.rcParams['figure.figsize']= 10,5 #设置图例尺寸
    plt.rcParams['font.sans-serif']=['SimHei'] #设置为中文黑体,如果设置楷体则为 KaiTi
    plt.rcParams['axes.unicode_minus']=False

    plt.scatter(x, y, color='b',label='间隔时间')
    plt.plot(x, slope*x + intercept, color='r',label='趋势回归线')
    plt.legend()      #绘制图例,右上角标识图
    plt.show()   

stats_linear_regression(trade_df)
slope is -0.11791958041958041

在这里插入图片描述

2. 数据密度计算正常状态/周期

基于聚类——数据密度(DBSCAN)提取典型(正常状态)特征,DBSCAN是基于一组邻域来描述样本集密度的空间聚类算法,将具有足够密度的区域划分为簇,参数 ( ϵ , M i n P t s ) (ϵ,MinPts) (ϵ,MinPts)用来描述邻域的样本分布紧密程度。其中, ϵ ϵ ϵ描述了某一样本的邻域距离阈值, M i n P t s MinPts MinPts描述了某一样本的距离为ϵ的邻域中样本个数的阈值。

通过DBSCan聚类分析各个客户交易行为规律,设 ∆ t ∆t t x x x,使用交易间隔天数的密度分簇,寻找最大的簇为“平常交易间隔天数 μ t μ_t μt”,与交易间隔天数平均值、中位数、众数相比,更接近实际情况。
例如图所示交易序列,中位数为15,均值为19.5,聚类最大簇的平均间隔时间μ_t为12天。

sklearn.cluster.DBSCAN参数

sklearn.cluster.DBSCAN(eps=0.5, *, min_samples=5, metric=‘euclidean’, metric_params=None, algorithm=‘auto’, leaf_size=30, p=None, n_jobs=None)

参数:

  • eps:两个样本之间的最大距离,其中一个样本被视为在另一个样本的邻域中。这不是簇内点距离的最大界限。这是为数据集和距离函数选择的最重要的DBSCAN参数。
  • min_samples:最小采样点,默认值=5
    将一个点视为核心点的邻域中的样本数(或总权重)。
  • metric:或可调用,默认值为“欧几里德”。
    计算要素阵列中实例之间的距离时使用的度量。如果metric是字符串或可调用,则它必须是sklearn.metrics.pairwise_distance为其metric参数所允许的选项之一。若度量是“预计算”的,则假定X是距离矩阵,且必须是平方。X可以是术语表,在这种情况下,只有“非零”元素可以被视为DBSCAN的邻居。
  • leaf_size,默认值=30。
    传递给BallTree或cKDTree的叶大小。这可能会影响构造和查询的速度,以及存储树所需的内存。最佳值取决于问题的性质。
  • n_jobs,整形数。 指定计算所用的进程数。内部原理是同时进行n_init指定次数的计算。
    (1)若值为 -1,则用所有的CPU进行运算。若值为1,则不进行并行运算,这样的话方便调试。
    (2)若值小于-1,则用到的CPU数为(n_cpus + 1 + n_jobs)。因此如果 n_jobs值为-2,则用到的CPU数为总CPU数减1。

属性:

  • labels_:给fit()的数据集中每个点的cluster label。噪声样本的标签为-1。
from sklearn.cluster import DBSCAN
from numpy import unique
import matplotlib.pyplot as plt

# 数据密度分析
def dbcsan_analysis(df): 
    user_df = df.loc[df['carduser_id']== 2085728 ].reset_index(drop=True)
       
    Days = user_df['days'].values
    Days = Days[1:]
    k = []
    for i in range(len(Days)):
        k.append(i)

    Days = Days.reshape(-1,1)
    dbs = DBSCAN(eps = 3, min_samples = 5).fit(Days)
    labels = dbs.labels_ 

    # 检索唯一群集
    clusters = unique(labels)
    k = np.array(k)
    k = k.reshape(-1)
    Days = Days.reshape(-1)
    
    plt.rcParams['font.sans-serif']=['SimHei'] #显示中文标签 KaiTi
    plt.rcParams['axes.unicode_minus']=False

    scatter = plt.scatter(k, Days, c=labels ,cmap='viridis') #'inferno')
    plt.show()  
    
    sub_df = user_df.drop(index=[0]).reset_index(drop=True) # 删除第一行,因为第一行的时间间隔不合理,或者不存在
    Days = sub_df[['days']].copy() # 间隔时间,建立副本处理
    Days['lables'] = labels
    Days = Days.loc[Days['lables']!=-1].reset_index(drop=True)

    count_group = Days[['lables','days']].groupby(by=['lables'],as_index=False).count()
    maxcount= count_group.sort_values(by=['days'], ascending = True).tail(1)[['lables']].values[0][0]
    
    count_mean = Days[['lables','days']].groupby(by=['lables'],as_index=False).mean()
    count_mean['days']= count_mean['days'].round(0)
    DBSan_mean = count_mean[['days']].loc[count_mean['lables']==maxcount].values[0][0]
    mean = Days[['days']].mean()
    
    median = Days[['days']].median()
    
    print(DBSan_mean)
    print(mean)
    print(median)
    
dbcsan_analysis(trade_df)

在这里插入图片描述

14.0
days    17.673469
days    15.0

3. 相关分析计算特征间关系

皮尔森相关系数 (Pearson Correlation) 是一种最简单的,能帮助理解特征和响应变量之间关系的方法,该方法衡量的是变量之间的线性相关性,结果的取值区间为 [ − 1 , 1 ] [ − 1 , 1 ] [11],-1表示完全的负相关,+1表示完全的正相关,0表示没有线性相关。

ρ X , Y = c o v ( X , Y ) σ X σ Y \rho_{X,Y}=\frac{cov(X,Y)}{\sigma _{X}\sigma_{Y}} ρX,Y=σXσYcov(X,Y)

ρ X , Y = ∑ i = 1 n ( X i − X ‾ ) ( Y i − Y ‾ ) ∑ i = 1 n ( X − X ‾ ) 2 ∑ i = 1 n ( Y − Y ‾ ) 2 \rho_{X,Y}=\frac{\sum_{i=1}^{n}(X_{i}-\overline{X})(Y_{i}-\overline{Y})}{\sqrt{\sum_{i=1}^{n}(X-\overline{X})^{2}}\sqrt{\sum_{i=1}^{n}(Y-\overline{Y})^{2}}} ρX,Y=i=1n(XX)2 i=1n(YY)2 i=1n(XiX)(YiY)

DataFrame.corr(method=‘pearson’, min_periods=1)

参数说明:

method:可选值为{‘pearson’, ‘kendall’, ‘spearman’}

  • pearson:Pearson相关系数来衡量两个数据集合是否在一条线上面,即针对线性数据的相关系数计算,针对非线性数据便会有误差。
  • kendall:用于反映分类变量相关性的指标,即针对无序序列的相关系数,非正太分布的数据
  • spearman:非线性的,非正太分布的数据的相关系数

min_periods:样本最少的数据量

返回值:各类型之间的相关系数DataFrame矩阵表格。

def pearson_corr(df):
    user_df = df.loc[df['carduser_id']== 2085728 ].reset_index(drop=True)
    relat = user_df[['volumn','amount']]
    pearson = relat.corr(method='pearson',min_periods=1)
    pv = round((pearson['amount'].values)[0],4)    
    
    return pv

pv = pearson_corr(trade_df)
print(pv)
0.9489

4. 归一化、标准化

现实的数据一般都是有单位的,比如常用身高的单位有米、厘米,这些情况会影响到数据分析的结果,这个无量纲化并不是说统一量纲为米,而是说,无论是米还是厘米,最后都会变成1,也就是没有了单位。无量纲化使不同规格的数据转换到同一规格。常见的无量纲化方法有标准化和归一化。

标准化(Z-Score)

x ′ = x i − μ σ x' = \frac{x_{i}- \mu }{\sigma} x=σxiμ
其中:

  • x ′ x' x—新值
  • x i x_{i} xi—输入值(原始值)
  • μ \mu μ σ \sigma σ表示 X i X_{i} Xi均值和标准差。

最大、最小值归一化(缩放)

x ′ = x i − x m i n x m a x − x m i n x'=\frac{x_{i}-x_{min}}{x_{max}-x_{min}} x=xmaxxminxixmin

其中:

  • x ′ x' x—输出新值,范围为 [ 0 , 1 ] [0,1] [0,1]
  • x i x_{i} xi—输入值(原始值)
  • x m i n x_{min} xmin—输入最小值
  • x m a x x_{max} xmax—输入最大值
from sklearn.preprocessing import StandardScaler
#特征归一化
def _feature_StandardScaler(data,normalization=True):       
    #数据归一化处理
    if normalization:
        scaler = StandardScaler()
        columns = data.columns
        indexs_train = data.index
        data = pd.DataFrame(scaler.fit_transform(data),index = indexs_train, columns = columns)

    return data
#原数据记录中,有日期等,不能做归一化,只选数值型数据
data = _feature_StandardScaler(df[['balance','recharge','volumn','all_oils','all_goods']])
print(data)
        balance  recharge    volumn  all_oils  all_goods
0     -0.529351 -0.393336 -1.346787  1.360023  -1.875326
1     -0.744385 -0.393336 -0.163501  0.150542   0.073976
2     -0.989514 -0.393336  0.047515 -0.018725   0.073976
3     -0.946507  0.307995  0.648507 -0.853328   0.073976
4     -0.989514  0.000515 -0.026894  0.029593  -0.393856
...         ...       ...       ...       ...        ...

5. 聚类——KMean

K-Means算法原理
对于给定的样本集,按照样本之间的距离大小,将样本集划分为K个簇。让簇内的点尽量紧密的连在一起,而让簇间的距离尽量的大。

该算法其采用聚类误差平方和函数 E E E作为聚类准则函数:
E = ∑ i = 1 k ∑ j = 1 n i ‖ x i j - m i ‖ 2 E = ∑_{i=1}^k∑_{j=1}^{n_i}‖x_{ij} - m_{i}‖^2 E=i=1kj=1nixijmi2
其中, n i n_{i} ni表示第 i i i 簇的样本个数;
x i j x_{ij} xij表示第 i i i 簇第 j j j 个样本;
m i m_i mi表示第 i i i 簇的聚类中心或质心。

m i = 1 N i ∑ j = 1 N i x i j m_i = \frac{1}{N_i}∑_{j=1}^{N_i}x_{ij} mi=Ni1j=1Nixij

sklearn.cluster.KMeans 参数介绍

sklearn.cluster.KMeans(
    n_clusters=8,
    init='k-means++', 
    n_init=10, 
    max_iter=300, 
    tol=0.0001, 
    precompute_distances='auto', 
    verbose=0, 
    random_state=None, 
    copy_x=True, 
    n_jobs=1, 
    algorithm='auto'
    )

参数:

  • n_clusters:整形,缺省值=8 【生成的聚类数,即产生的质心(centroids)数。】
  • max_iter:整形,缺省值=300,执行一次k-means算法所进行的最大迭代数。
  • n_init:整形,缺省值=10,用不同的质心初始化值运行算法的次数,最终解是在inertia意义下选出的最优结果。
  • init:有三个可选值:’k-means++’, ‘random’,或者传递一个ndarray向量。
    此参数指定初始化方法,默认值为 ‘k-means++’。
    (1)‘k-means++’ 用一种特殊的方法选定初始质心从而能加速迭代过程的收敛
    (2)‘random’ 随机从训练数据中选取初始质心。
    (3)如果传递的是一个ndarray,则应该形如 (n_clusters, n_features) 并给出初始质心。
  • precompute_distances:三个可选值,‘auto’,True 或者 False。
    预计算距离,计算速度更快但占用更多内存。
    (1)‘auto’:如果 样本数乘以聚类数大于 12million 的话则不预计算距离。
    (2)True:总是预先计算距离。
    (3)False:永远不预先计算距离。
  • tol:float形,默认值= 1e-4 与inertia结合来确定收敛条件。
  • n_jobs:整形数。 指定计算所用的进程数。内部原理是同时进行n_init指定次数的计算。
    (1)若值为 -1,则用所有的CPU进行运算。若值为1,则不进行并行运算,这样的话方便调试。
    (2)若值小于-1,则用到的CPU数为(n_cpus + 1 + n_jobs)。因此如果 n_jobs值为-2,则用到的CPU数为总CPU数减1。
  • random_state:整形或 numpy.RandomState 类型,可选
    用于初始化质心的生成器(generator)。如果值为一个整数,则确定一个seed。此参数默认值为numpy的随机数生成器。
  • copy_x:布尔型,默认值=True
    当我们precomputing distances时,将数据中心化会得到更准确的结果。如果把此参数值设为True,则原始数据不会被改变。如果是False,则会直接在原始数据
    上做修改并在函数返回值时将其还原。但是在计算过程中由于有对数据均值的加减运算,所以数据返回后,原始数据和计算前可能会有细小差别。

属性:

  • cluster_centers_:向量,[n_clusters, n_features] (聚类中心的坐标)
  • Labels_: 每个点的分类
  • inertia_:float形,每个点到其簇的质心的距离之和。

这个k-means运用了 Lioyd’s 算法,平均计算复杂度是 O(knT),其中n是样本量,T是迭代次数。
计算复杂读在最坏的情况下为 O ( n ( k + 2 p ) ) O(n^{(\frac{k+2}{p}))} O(n(pk+2)),其中n是样本量,p是特征个数。
在实践中,k-means算法时非常快的,属于可实践的算法中最快的那一类。但是它的解只是由特定初始值所产生的局部解。所以为了让结果更准确真实,在实践中要用不同的初始值重复几次才可以。

from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.cluster import KMeans
import pandas as pd
import numpy as np
Input_file = 'card0705_clustering.csv'
marks_name = 'marks'
params_name = ['carduser_id','latestday','occurtime','org_rate','balance']

df = pd.read_csv(Input_file) 
#print(df)
# KMean聚类
def KMean_analysis(df,cols_names,marks_name,params_name):
    Flag = list(df[marks_name])
    cols = cols_names.copy()
    for id_name in params_name:
        cols.remove(id_name)
    cols.remove(marks_name)
    dd=df[cols]     
    samples=dd.values

    #标准化
    scaler=StandardScaler()

    kmeans=KMeans(n_clusters=2,random_state=1,max_iter=3000)
    pipeline=make_pipeline(scaler,kmeans)
    pipeline.fit(samples) #训练模型
    labels=pipeline.predict(samples)#预测
    dd=df[cols_names]
    dd['flag'] = labels

    df_cluster=pd.DataFrame({'labels':labels,'Flag':Flag})
    ct=pd.crosstab(df_cluster['labels'],df_cluster['Flag'])
    print('K-Means')
    print(ct)
cols_names = ['carduser_id','latestday','balance','balancerate',
    'IntervalSlope','IntervalStd','latestdays','tradecount','BalanceSlope','BalanceStd',
    'AmountSlope','AmountStd','amountmean','VolumnSlope','VolumnStd','recharge_days',
    'balancemean','goodsmean','volumnmean','sumamount','amountrate','volumn','volumnrate','meandays','maxdaysrate','latestdaysrate','daysnum',
    'tradecountSlope','tradecountStd','monthnum','days','Rechargeslope','RechargeStd',
    'maxvolumn','accsumamount','accamount','accgoods','accvolumn','maxrecharge','meanrecharge','lastrecharge','rechargerate',
    'densitymean','MinIntervalByPrice','marks','occurtime','count','pearson','org_rate']  
KMean_analysis(df,cols_names,marks_name,params_name)
K-Means
Flag         0      1      2
labels                      
0       154123  97324  72259
1        68510  19569   9440

6. 小结

在挖掘交易明细数据的基础上,再通过机器学习方法和技术,可以增强特征,这样,使用简单的机器学习算法预测出较好的结果。

参考:

[1] . 肖永威 . Pandas高级数据分析快速入门之三——数据挖掘与统计分析篇,CSDN博客 ,2021年8月
[2] . 肖永威 . Pandas高级数据分析快速入门之四——数据可视化篇,CSDN博客 ,2021年8月

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

肖永威

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值