《python数据挖掘》实战篇


6章:分类-窃电用户自动识别

 目标

  模型构建LM-NETCART

   数据划分

        LM神经网络

       cart决策树

  模型评价ROC

7章:聚类-航空公司客户价值分析

1RFM模型-传统

目标

    1分析方法与过程-数据预处理

    2构建kmeans模型(无代码:参考模型章节

8章:关联规则-中医证型挖掘

目标:

过程

   属性离散化

模型-关联规则有问题-

9章:分类-基于水色图像的水质评价

Svm模型

10:家用电器用户行为分析与时间识别

目标

过程

    1数据抽取:无放回随机抽样法

    2探索分析

    3数据预处理

    4构建专家样本:找资料进行合适的数据构造

模型

    阈值寻优模型

    用水事件的划分-阈值处理

    洗浴识别模型-BP神经网络分类

    模型检验-准确率

11:时间序列-应用系统负载分析与容量预测

目标

分析

    探索分析:周期性分析

数据预处理

    容量预测模型

    平稳性检验:

    白噪声检验:

            AIC定阶

    模型检验

    模型预测

模型评价与应用

12章 :电子商务网站用户行为分析及服务推荐(基于协同过滤算法)

https://blog.csdn.net/u012063773/article/details/79324194

目的

数据探索

    导入sql数据

    网页类型统计

数据预处理

模型构建-具体参考链接网页

13预测-财政收入影响因素分析及预测模型

目标

数据探索分析

数据预处理

模型

    变量选择模型lasso或者AdaptiveLasso

    灰色预测与神经网络的组合模型

14层次聚类-基于基站定位数据的商圈分析

目标

探索分析

模型-层次聚类

    1谱聚类

    2层次聚类

15章:电商产品评论数据情感分析代码详解目标

数据预处理

    2文本去重

    4结巴分词

模型-LDA

 

6章:分类-窃电用户自动识别

目标

归纳出窃漏电用户的关键特征,构建窃漏电用户的识别模型;

利用实时监测数据,调用窃漏电用户识别模型实现实时诊断。

先按照前面的几章节处理数据

模型构建LM-NETCART

数据划分

import pandas as pd
from random import shuffle

datafile = '../data/model.xls'
data = pd.read_excel(datafile)
data = data.as_matrix()
shuffle(data)

p = 0.8 #设置训练数据比例
train = data[:int(len(data)*p),:]
test = data[int(len(data)*p):,:]

LM神经网络



from keras.models import Sequential #导入神经网络初始化函数
from keras.layers.core import Dense, Activation #导入神经网络层函数、激活函数

net = Sequential() #建立神经网络
net.add(Dense(10,input_dim=3)) #添加输入层(3节点)到隐藏层(10节点)的连接
net.add(Activation('relu')) #隐藏层使用relu激活函数
net.add(Dense(1,input_dim=10)) #添加隐藏层(10节点)到输出层(1节点)的连接
net.add(Activation('sigmoid')) #输出层使用sigmoid激活函数
net.compile(loss = 'binary_crossentropy', optimizer = 'adam') #, class_mode = "binary"编译模型,使用adam方法求解

net.fit(train[:,:3], train[:,3], epochs=1000, batch_size=1) #训练模型,循环1000次
netfile = '../tmp/net1.model' #构建的神经网络模型存储路径
net.save_weights(netfile) #保存模型

predict_result = net.predict_classes(train[:,:3]).reshape(len(train)) #预测结果变形
'''这里要提醒的是,keras用predict给出预测概率,predict_classes才是给出预测类别,而且两者的预测结果都是n x 1维数组,而不是通常的 1 x n'''

from
cm_plot import * #导入自行编写的混淆矩阵可视化函数
cm_plot(train[:,3], predict_result).show() #显示混淆矩阵可视化结果

cart决策树

#构建CART决策树模型
from sklearn.tree import DecisionTreeClassifier #导入决策树模型
tree = DecisionTreeClassifier() #建立决策树模型
tree.fit(train[:,:3], train[:,3]) #训练
#保存模型
from sklearn.externals import joblib
joblib.dump(tree,  '../tmp/tree.pkl')#模型持久化的操作,导入joblib即
predict_result=tree.predict(train[:,:3])#注意到Scikit-Learn使用predict方法直接给出预测结果。

 

模型评价ROC

from sklearn.metrics import roc_curve #导入ROC曲线函数
fpr, tpr, thresholds = roc_curve(test[:,3], predict_result, pos_label=1)
plt.plot(fpr, tpr, linewidth=2, label = 'ROC of CART', color = 'green') #作出ROC曲线
plt.xlabel('False Positive Rate') #坐标轴标签
plt.ylabel('True Positive Rate') #坐标轴标签
plt.ylim(0,1.05) #边界范围
plt.xlim(0,1.05) #边界范围
plt.legend(loc=4) #图例位置
plt.show() #显示作图结果

 

 

7章:聚类-航空公司客户价值分析

1RFM模型-传统

广泛用于分析客户价值的是RFM模型,它是通过三个指标(最近消费时间间隔(Recency)、消费频率(Frequency)、消费金额(Monetary))来进行客户细分,识别出高价值的客户。

目标

借助航空公司客户数据,对客户进行分类;

对不同的客户类别进行特征分析,比较不同类客户的客户价值;

对不同价值的客户类别提供个性化服务,制定相应的营销策略

 

1分析方法与过程-数据预处理

初步分析:提出适用航空公司的LRFMC模型

因消费金额指标在航空公司中不适用,故选择客户在一定时间内累积的飞行里程M和客户乘坐舱位折扣系数的平均值C两个指标代替消费金额。此外,考虑航空公司会员加入时间在一定程度上能够影响客户价值,所以在模型中增加客户关系长度L,作为区分客户的另一指标,因此构建出LRFMC模型。

 

采用聚类的方法对客户进行细分,并分析每个客户群的特征,识别其客户价值。

1数据探索describe(代码省略)

2数据清洗:选取需要的特征

#选择需要的数据
data = data[data['SUM_YR_1'].notnull()&data['SUM_YR_2'].notnull()] #丢弃票价为空的记录
#丢弃票价为零,或者平均折扣率与总飞行公里数不0的记录。
index1 = data['SUM_YR_1'] != 0#只保留票价非零的,或者平均折扣率与总飞行公里数同时为0的记录。
index2 = data['SUM_YR_2'] != 0
index3 = (data['SEG_KM_SUM'] == 0) & (data['avg_discount'] == 0) #该规则是“与”
data = data[index1 | index2 | index3] #该规则是“或”

3属性规约:原始数据中属性太多,根据LRFMC模型,选择与其相关的六个属性,删除不相关、弱相关或冗余的属性。

4、数据变换

1)属性构造

L = LOAD_TIME - FFP_DATE

会员入会时间距观测窗口结束的月数 = 观测窗口的结束时间 - 入会时间[单位:月

R = LAST_TO_END

客户最近一次乘坐公司飞机距观测窗口结束的月数 = 最后一次乘机时间至观察窗口末端时长[单位:月]

F = FLIGHT_COUNT

客户在观测窗口内乘坐公司飞机的次数 = 观测窗口的飞行次数[单位:次]

M = SEG_KM_SUM

客户在观测时间内在公司累计的飞行里程 = 观测窗口总飞行公里数[单位:公里]

C = AVG_DISCOUNT

客户在观测时间内乘坐舱位所对应的折扣系数的平均值 = 平均折扣率[单位:无]

 

2)数据标准化

2构建kmeans模型(无代码:参考模型章节

客户K-Means聚类-客户价值分析-模型应用

8章:关联规则-中医证型挖掘

目标:

借助三阴乳腺癌患者的病理信息,挖掘患者的症状与中医证型之间的关联关系;

对截断治疗提供依据,挖掘潜性证素。

过程

数据收集-数据清洗-

数据规约:删除不相关属性,选取其中六种证型得分、患者编号和TNM分期属性。

数据变换:

1)属性构造:为了更好的反应出中医证素分布的特征,采用证型系数代替具体单证型的证素得分,证型相关系数计算公式如下:证型系数 = 该证型得分/该证型总分

2)属性离散化

Aprior关联规则无法处理连续型变量,需要聚类进行离散化处理

#-*- coding: utf-8 -*-
'''
聚类离散化,最后的result的格式为:
      1           2           3           4
A     0    0.178698    0.257724    0.351843
An  240  356.000000  281.000000   53.000000
(0, 0.178698]有240个,(0.178698, 0.257724]有356个,依此类推。
'''
import pandas as pd
from sklearn.cluster import KMeans #导入K均值聚类算法

datafile = '../data/data.xls' #待聚类的数据文件
processedfile = '../tmp/data_processed.xls' #数据处理后文件
typelabel ={u'肝气郁结证型系数':'A', u'热毒蕴结证型系数':'B', u'冲任失调证型系数':'C', u'气血两虚证型系数':'D', u'脾胃虚弱证型系数':'E', u'肝肾阴虚证型系数':'F'}
k = 4 #需要进行的聚类类别数

#读取数据并进行聚类分析
data = pd.read_excel(datafile) #读取数据
keys = list(typelabel.keys())#标题6个类别变成列表
result = pd.DataFrame()

if __name__ == '__main__': #判断是否主窗口运行,如果是将代码保存为.py后运行,则需要这句,如果直接复制到命令窗口运行,则不需要这句。
  
for i in range(len(keys)):
    #调用k-means算法,进行聚类离散化
    
print(u'正在进行“%s”的聚类...' % keys[i])
    kmodel = KMeans(n_clusters = k, n_jobs = 4) #n_jobs是并行数,一般等于CPU数较好
    
kmodel.fit(data[[keys[i]]].as_matrix()) #训练模型
    
    
r1 = pd.DataFrame(kmodel.cluster_centers_, columns = [typelabel[keys[i]]]) #聚类中心
    
r2 = pd.Series(kmodel.labels_).value_counts() #分类统计
    
r2 = pd.DataFrame(r2, columns = [typelabel[keys[i]]+'n']) #转为DataFrame,记录各个类别的数目
    
r = pd.concat([r1, r2], axis = 1).sort(typelabel[keys[i]]) #匹配聚类中心和类别数目
    
r.index = [1, 2, 3, 4]
    
    r[typelabel[keys[i]]] = pd.rolling_mean(r[typelabel[keys[i]]], 2) #rolling_mean()用来计算相邻2列的均值,以此作为边界点。
    
r[typelabel[keys[i]]][1] = 0.0 #这两句代码将原来的聚类中心改为边界点。
    
result = result.append(r.T)

  result = result.sort() #以Index排序,即以A,B,C,D,E,F顺序排
  
result.to_excel(processedfile)

 

模型-关联规则有问题-

#-*- coding: utf-8 -*-
from __future__ import print_function
import pandas as pd
from apriori import * #导入自行编写的apriori函数
import time #导入时间库用来计算用时

inputfile = '../data/apriori.txt' #输入事务集文件
data = pd.read_csv(inputfile, header=None, dtype = object)

start = time.clock() #计时开始
print(u'\n转换原始数据至0-1矩阵...')
ct = lambda x : pd .Series(1, index = x[pd.notnull(x)]) #转换0-1矩阵的过渡函数
b = map(ct, data.as_matrix()) #用map方式执行
data = pd.DataFrame(b).fillna(0) #实现矩阵转换,空值用0填充
end = time.clock() #计时结束
print(u'\n转换完毕,用时:%0.2f秒' %(end-start))
del b #删除中间变量b,节省内存

support = 0.06 #最小支持度
confidence = 0.75 #最小置信度
ms = '---' #连接符,默认'--',用来区分不同元素,如A--B。需要保证原始表格中不含有该字符

start = time.clock() #计时开始
print(u'\n开始搜索关联规则...')
find_rule(data, support, confidence, ms)
end = time.clock() #计时结束
print(u'\n搜索完成,用时:%0.2f秒' %(end-start))

9章:分类-基于水色图像的水质评价

图像特征:颜色,纹理,形状,空间,颜色有鲁棒性,本案例水色图样均匀看颜色

颜色特征:颜色直方图法、颜色矩

图像切割

特征提取:三阶分别表示:明暗,颜色分布范围,分布的对称性

构建模型LM水质评价分类模型

Svm模型

#-*- coding: utf-8 -*-
import pandas as pd

inputfile = '../data/moment.csv' #数据文件
outputfile1 = '../tmp/cm_train.xls' #训练样本混淆矩阵保存路径
outputfile2 = '../tmp/cm_test.xls' #测试样本混淆矩阵保存路径
data = pd.read_csv(inputfile, encoding = 'gbk') #读取数据,指定编码为gbk
data = data.as_matrix()

from numpy.random import shuffle #引入随机函数
shuffle(data) #随机打乱数据
data_train = data[:int(0.8*len(data)), :] #选取前80%为训练数据
data_test = data[int(0.8*len(data)):, :] #选取前20%为测试数据

#构造特征和标签
x_train = data_train[:, 2:]*30
y_train = data_train[:, 0].astype(int)
x_test = data_test[:, 2:]*30
y_test = data_test[:, 0].astype(int)

#导入模型相关的函数,建立并且训练模型
from sklearn import svm
model = svm.SVC()
model.fit(x_train, y_train)
import pickle
pickle.dump(model, open('../tmp/svm.model', 'wb'))
#最后一句保存模型,以后可以通过下面语句重新加载模型:
#model = pickle.load(open('../tmp/svm.model', 'rb'))

#导入输出相关的库,生成混淆矩阵
from sklearn import metrics
cm_train = metrics.confusion_matrix(y_train, model.predict(x_train)) #训练样本的混淆矩阵
cm_test = metrics.confusion_matrix(y_test, model.predict(x_test)) #测试样本的混淆矩阵

#保存结果
pd.DataFrame(cm_train, index = range(1, 6), columns = range(1, 6)).to_excel(outputfile1)
pd.DataFrame(cm_test, index = range(1, 6), columns = range(1, 6)).to_excel(outputfile2)

第10章 :家用电器用户行为分析与时间识别

目标

根据热水器采集到的数据,划分一次完整用水事件;

在划分好的一次完整用水事件中,识别出洗浴事件。

过程

1数据抽取:无放回随机抽样法
2探索分析

为了探究用户真实用水停顿时间间隔的分布情况,统计用水停顿的时间间隔并作频率分布直方图。

 

停顿时间间隔为0~0.3分钟的频率很高,根据日常用水经验可以判断其为一次用水时间中的停顿;停顿时间间隔为6~13分钟的频率较低,分析其为两次用水事件之间的停顿间隔。两次用水事件的停顿时间间隔分布在3~7分钟与现场实验统计用水停顿的时间间隔近似。

3数据预处理

数据规约

1数据规约

属性规约:因“热水器编号”、“即热”、“即时洗” 、“有无水流” 、“预约洗”、 “节能模式”对建模无作用,可以去除

数值规约:当热水器“开关机状态”为“关”且水流量为0时,说明热水器不处于工作状态,数据记录可以规约掉。

2数据变换

1)一次完整用水事件的划分:不用水时间>阈值,就是停止用水,不是暂时停止

2)用水事件阈值寻优:根据水流量和停顿时间间隔的阈值划分一次完整的用水事件。

3)属性构造:根据用水行为,需构造四类指标:时长指标、频率指标、用水的量化指标以及用水的波动指标。

 

4)候选洗浴事件:体积和(总)用水时长<某个值不算

  现实中:经过实验分析,热水器设定温度为50摄氏度时,一次普通的洗浴时长为15分钟,总用水时长10分钟左右,热水的使用量为10~15升。

3 缺失值处理

结合实际问题添加:因存在网络故障等原因,导致用水数据状态记录缺失的情况,需要对缺失的数据状态记录进行添加。其添加方法:用水状态记录缺失的情况下,填充一条状态记录使水流量为0,发生时间加2秒,其余属性状态不变。

 

4构建专家样本:找资料进行合适的数据构造

模型

阈值寻优模型

#阈值寻优模型
import numpy as np
import pandas as pd
inputfile = '../data/water_heater.xls' #输入数据路径,需要使用Excel格式

threshold = pd.Timedelta(minutes = 5) #专家阈值
data = pd.read_excel(inputfile)
data[u'发生时间'] = pd.to_datetime(data[u'发生时间'], format = '%Y%m%d%H%M%S')
data = data[data[u'水流量'] > 0] #只要流量大于0的记录
#计算时间在某个阈值的数目
def event_num(ts):
  d = data[u'发生时间'].diff() > ts #相邻时间作差分,比较是否大于阈值
  
return d.sum() + 1 #这样直接返回事件数

dt = [pd.Timedelta(minutes = i) for i in np.arange(1, 9, 0.25)]#list,1-9分钟,每一刻一次[Timedelta('0 days 00:01:00'), Timedelta('0 days 00:01:15'),
h = pd.DataFrame(dt, columns = [u'阈值']) #定义阈值列,
h[u'事件数'] = h[u'阈值'].apply(event_num) #计算每个阈值对应的事件数
h[u'斜率'] = h[u'事件数'].diff()/0.25 #计算每两个相邻点对应的斜率
n=4#获取比较平缓的时间,斜率,找斜率指标最小
h[u'斜率指标'] = pd.rolling_mean(h[u'斜率'].abs(),n) #采用后n个的斜率绝对值平均作为斜率指标
ts = h[u'阈值'][h[u'斜率指标'].idxmin() - n]
#注:用idxmin返回最小值的Index,由于rolling_mean()自动计算的是前n个斜率的绝对值平均,所以结果要进行平移(-n)

if ts > threshold:
  ts = pd.Timedelta(minutes = 4)#小于5,经过专家验证
print(ts)

用水事件的划分-阈值处理

#用水事件划分
import pandas as pd
threshold = pd.Timedelta('4 min') #阈值为分钟Timedelta
inputfile = '../data/water_heater.xls' #输入数据路径,需要使用Excel格式
outputfile = '../tmp/dividsequence.xls' #输出数据路径,需要使用Excel格式

data = pd.read_excel(inputfile)
data[u'发生时间'] = pd.to_datetime(data[u'发生时间'], format = '%Y%m%d%H%M%S')#to_datetime
data = data[data[u'水流量'] > 0] #只要流量大于0的记录
d = data[u'发生时间'].diff() > threshold #相邻时间作差分,比较是否大于阈值
data[u'事件编号'] = d.cumsum() + 1 #通过累积求和的方式为事件编号,true一次就+1

data.to_excel(outputfile)

 

洗浴识别模型-BP神经网络分类

#建立、训练多层神经网络,并完成模型的检验
import pandas as pd

inputfile1='../data/train_neural_network_data.xls' #训练数据
inputfile2='../data/test_neural_network_data.xls' #测试数据
testoutputfile = '../tmp/test_output_data1.xls' #测试数据模型输出文件
data_train = pd.read_excel(inputfile1) #读入训练数据(由日志标记事件是否为洗浴)
data_test = pd.read_excel(inputfile2) #读入测试数据(由日志标记事件是否为洗浴)
y_train = data_train.iloc[:,4].as_matrix() #训练样本标签列
x_train = data_train.iloc[:,5:17].as_matrix() #训练样本特征
y_test = data_test.iloc[:,4].as_matrix() #测试样本标签列
x_test = data_test.iloc[:,5:17].as_matrix() #测试样本特征

from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation
model = Sequential() #建立模型
model.add(Dense(17,input_dim=11)) #添加输入层、隐藏层的连接
model.add(Activation('relu')) #以Relu函数为激活函数
model.add(Dense(10,input_dim=17)) #添加隐藏层、隐藏层的连接
model.add(Activation('relu')) #以Relu函数为激活函数
model.add(Dense(1,input_dim=10)) #添加隐藏层、输出层的连接
model.add(Activation('sigmoid')) #以sigmoid函数为激活函数
#编译模型,损失函数为binary_crossentropy,用adam法求解
model.compile(loss='binary_crossentropy', optimizer='adam', class_mode="binary") #, class_mode="binary"去掉不知道行不行

model.fit(x_train, y_train, epochs  = 100, batch_size = 1) #训练模型
model.save_weights('../tmp/net.model') #保存模型参数
#model.load_weights('../tmp/net.model')
r = pd.DataFrame(model.predict_classes(x_test), columns = [u'预测结果'])
pd.concat([data_test.iloc[:,:5], r], axis = 1).to_excel(testoutputfile)
model.predict(x_test)

模型检验-准确率

第11章 :时间序列-应用系统负载分析与容量预测

目标

针对历史磁盘数据,采用数据挖掘的方法,预测应用系统服务器磁盘已使用空间大小

根据用户需求设置不同的预警等级,将预测值与容量值进行比较,对其结果进行预警判断,为系统管理员提供定制化的预警提示

分析

在不考虑人为因素的影响时,存储空间随时间变化存在很强的关联性,且历史数据对未来的发展存在一定的影响,故可采用时间序列分析法对磁盘已使用空间进行预测分析。

探索分析:周期性分析

对数据进行周期性分析,探索数据的平稳性

import pandas as pd

datafile = '../data/discdata.xls'
data = pd.read_excel(datafile)
data1 = data[(data['ENTITY'] == 'C:\\') & (data['TARGET_ID'] == 184)]

import datetime
import matplotlib.dates as mdates
import matplotlib.pyplot as plt


fig = plt.figure()
ax = fig.add_subplot(2, 1, 1)
ax.set_title(u'C盘空间')
ax.set(xlabel=u'时间', ylabel=u'C磁盘空间')
# 图上时间间隔显示为10天
ax.xaxis.set_major_locator(mdates.DayLocator(bymonthday=range(1, 32), interval=10))
ax.xaxis.set_major_formatter(mdates.DateFormatter("%Y-%m-%d"))
plt.rc('figure', figsize=(9, 7))
plt.subplots_adjust(bottom=0.13, top=0.95)
ax.plot(data1['COLLECTTIME'], data1['VALUE'], 'ro-', )

fig.autofmt_xdate()  # 自动根据标签长度进行旋转  
'''''for label in ax.xaxis.get_ticklabels():   #此语句完成功能同上
       label.set_rotation(45)
'''
plt.savefig('c.jpg')
plt.show()

 

数据预处理

1数据清洗

实际业务中,监控系统会每天定时对磁盘的信息进行收集,但是磁盘容量属性一般情况下都是一个定值(不考虑中途扩容的情况),因此磁盘原始数据中会存在磁盘容量的重复数据。

剔除磁盘容量的重复数据。

将所有服务器的磁盘容量作为一个固定值,方便模型预警时需要。

data.drop_duplicates(data.columns[:-1],inplace=True)

属性构造:因每台服务器的磁盘信息可以通过表中NAMETARGET_IDENTITY三个属性进行区分,且每台服务器的上述三个属性值是不变的,所以可以将三个属性的值进行合并。 (实质是将行转换成列)

#属性变换
#参数初始化
data = data[data['TARGET_ID'] == 184].copy() #只保留TARGET_ID为184的数据

data_group = data.groupby('COLLECTTIME') #以时间分组

def attr_trans(x): #定义属性变换函数
  
result = pd.Series(index = ['SYS_NAME', 'CWXT_DB:184:C:\\', 'CWXT_DB:184:D:\\',  'COLLECTTIME'])
  result['SYS_NAME'] = x['SYS_NAME'].iloc[0]
  result['COLLECTTIME'] = x['COLLECTTIME'].iloc[0]
  result['CWXT_DB:184:C:\\'] = x['VALUE'].iloc[0]
  result['CWXT_DB:184:D:\\'] = x['VALUE'].iloc[1]
  return result

data_processed = data_group.apply(attr_trans) #逐组处理
data_processed.to_excel(transformeddata, index = False)

容量预测模型

模型流程图

 

平稳性检验:

为了确定原始数据序列中没有随机趋势或趋势,需要对数据进行平稳性检验,否则将会产生“伪回归”的现象。方法:单位跟检验或者观察时序图。

#-*- coding: utf-8 -*-
#平稳性检验
import pandas as pd

#参数初始化
discfile = '../data/discdata_processed.xls'
predictnum =5 #不使用最后5个数据

data = pd.read_excel(discfile)
data = data.iloc[: len(data)-5] #不检测最后5个数据

#平稳性检测
from statsmodels.tsa.stattools import adfuller as ADF
diff = 0
adf = ADF(data['CWXT_DB:184:D:\\'])
while adf[1] > 0.05:
  diff = diff + 1
  adf = ADF(data['CWXT_DB:184:D:\\'].diff(diff).dropna())

print(u'原始序列经过%s阶差分后归于平稳,p值为%s' %(diff, adf[1]))

 

白噪声检验:

为了验证序列中有用的信息是否已被提取完毕,需要对序列进行白噪声检验。如果序列检验为白噪声序列,就说明序列中有用的信息已经被提取完毕了,剩下的全是随机扰动,无法进行预测和使用。方法:一般采用LB统计量检验方法。

白噪声过程:对对于一个纯随机过程来说,其期望为0方差为常数

 

#参数初始化
discfile = '../data/discdata_processed.xls'
data = pd.read_excel(discfile)
data = data.iloc[: len(data)-5] #不使用最后5个数据

#白噪声检测
from statsmodels.stats.diagnostic import acorr_ljungbox
[[lb], [p]] = acorr_ljungbox(data['CWXT_DB:184:D:\\'], lags = 1)
if p < 0.05:print(u'原始序列为非白噪声序列,对应的p值为:%s' %p)
else:print(u'原始该序列为白噪声序列,对应的p值为:%s' %p)

[[lb], [p]] = acorr_ljungbox(data['CWXT_DB:184:D:\\'].diff().dropna(), lags = 1)
if p < 0.05: print(u'一阶差分序列为非白噪声序列,对应的p值为:%s' %p)
else:  print(u'一阶差分该序列为白噪声序列,对应的p值为:%s' %p)

AIC定阶

通过AIC、BIC信息准则或者观测自相关图和偏自相关图确定P、Q的参数,识别其模型属于AR、MA和ARMA中的哪一种模型。

AIC信息准则即Akaike information criterion,是衡量统计模型拟合优良性的一种标准所以优先考虑的模型应是AIC值最小的那一个

参数估计:估计模型的其他参数。可以采用极大似然估计、条件最小二乘法确定。

#-*- coding: utf-8 -*-
#确定最佳p、d、q值
import pandas as pd

#参数初始化
discfile = '../data/discdata_processed.xls'
data = pd.read_excel(discfile, index_col = 'COLLECTTIME')
xdata = data['CWXT_DB:184:D:\\']

from statsmodels.tsa.arima_model import ARIMA

#定阶
pmax = int(len(xdata)/10) #一般阶数不超过length/10
qmax = int(len(xdata)/10) #一般阶数不超过length/10
bic_matrix = [] #bic矩阵
for p in range(pmax+1):
  tmp = []
  for q in range(qmax+1):
    try: #存在部分报错,所以用try来跳过报错。
      
tmp.append(ARIMA(xdata, (p,1,q)).fit().bic)

      #tmp.append(ARMA(xdata2, (p,q)).fit().aic) #  AIC方式  
      #tmp.append(ARMA(xdata2, (p,q)).fit().hq) # HQ方式  

    except:
      tmp.append(None)
  bic_matrix.append(tmp)

bic_matrix = pd.DataFrame(bic_matrix) #从中可以找出最小值
p,q = bic_matrix.stack().idxmin() #先用stack展平,然后用idxmin找出最小值位置。
print(u'BIC最小的p值和q值为:%s、%s' %(p,q))

#BIC最小的p值和q值为:0、2

 

模型检验

确定模型后,需要检验其残差序列是否是白噪声,若不是,说明,残差中还存在有用的信息,需要修改模型或者进一步提取。若其残差不是白噪声,重新更换p,q的值,重新确定

#模型检验
import pandas as pd
#参数初始化
discfile = '../data/discdata_processed.xls'
lagnum = 12 #残差延迟个数
data = pd.read_excel(discfile, index_col = 'COLLECTTIME')
data = data.iloc[: len(data)-5] #不使用最后5个数据
xdata = data['CWXT_DB:184:D:\\']

from statsmodels.tsa.arima_model import ARIMA #建立ARIMA(0,1,1)模型
arima = ARIMA(xdata, (0, 1, 1)).fit() #建立并训练模型
xdata_pred = arima.predict(typ = 'levels') #预测
pred_error = (xdata_pred - xdata).dropna() #计算残差

from statsmodels.stats.diagnostic import acorr_ljungbox #白噪声检验
lb, p= acorr_ljungbox(pred_error, lags = lagnum)
h = (p < 0.05).sum() #p值小于0.05,认为是非白噪声。
if h > 0:print(u'模型ARIMA(0,1,1)不符合白噪声检验')
else:print(u'模型ARIMA(0,1,1)符合白噪声检验')

模型预测

model = ARIMA(data, (p,1,q)).fit() #建立ARIMA(0, 1, 1)模型
model.summary2() #给出一份模型报告
model.forecast(5) #作为期5天的预测,返回预测结果、标准误差、置信区间。

模型评价与应用


file = '../data/predictdata.xls'
data = pd.read_excel(file)
#计算误差
abs_ = (data[u'预测值'] - data[u'实际值']).abs()
mae_ = abs_.mean() # mae
rmse_ = ((abs_**2).mean())**0.5 # rmse
mape_ = (abs_/data[u'实际值']).mean() # mape

print(u'平均绝对误差为:%0.4f,\n均方根误差为:%0.4f,\n平均绝对百分误差为:%0.6f。' %(mae_, rmse_, mape_))

应用:根据预测的使用率进行警报

第12章 :电子商务网站用户行为分析及服务推荐(基于协同过滤算法)

https://blog.csdn.net/u012063773/article/details/79324194

目的

了解用户行为以及网站关心内容

借助访问记录,发现访问习惯,进行推荐

数据探索

导入sql数据

import pandas as pd

from sqlalchemy import create_engine

 

engine = create_engine('mysql+pymysql://root:123456@127.0.0.1:3306/test?charset=utf8')

sql = pd.read_sql('all_gzdata', engine, chunksize = 10000)

'''

create_engine建立连接,连接地址的意思依次为“数据库格式(mysql)+程序名(pymysql)+账号密码@地址端口/数据库名(test)”,最后指定编码为utf8;

all_gzdata是表名,engine是连接数据的引擎,chunksize指定每次读取1万条记录。这时候sql是一个容器,未真正读取数据。

'''

网页类型统计

counts = [ i['fullURLId'].value_counts() for i in sql] #逐块统计

counts = pd.concat(counts).groupby(level=0).sum() #level=0合并统计结果,把相同的统计项合并(即按index分组并求和)

counts = counts.reset_index() #重新设置index,将原来的index作为counts的一列。

counts.columns = ['index', 'num'] #重新设置列名,主要是第二列,默认为0

counts['type'] = counts['index'].str.extract('(\d{3})') #提取前三个数字作为类别id

counts_ = counts[['type', 'num']].groupby('type').sum() #按类别合并

counts_['ratio']=counts_/counts_.sum() #增加比例列

counts_.sort('num', ascending = False) #降序排列

 

#统计其他类别的情况def counts_type(type):

    counts_type=counts[counts['type']==type][['index', 'num']]

    counts_type['ratio']=counts_type['num']/counts_type['num'].sum()

    return counts_type.sort_values('num', ascending = False)

 

counts_type('102')   

 

#统计107类别的情况

def count107(i): #自定义统计函数

  j = i[['fullURL']][i['fullURLId'].str.contains('107')].copy() #找出类别包含107的网址

  j['type'] = None #添加空列

  j['type'][j['fullURL'].str.contains('info/.+?/')] = u'知识首页'

  j['type'][j['fullURL'].str.contains('info/.+?/.+?')] = u'知识列表页'

  j['type'][j['fullURL'].str.contains('/\d+?_*\d+?\.html')] = u'知识内容页'

  return j['type'].value_counts()

 

counts2 = [count107(i) for i in sql] #逐块统计

counts2 = pd.concat(counts2).groupby(level=0).sum() #合并统计结果

 

#瞎逛统计没有单击具体的页面(html结尾),他们单机的大部分是目录网页

sql = pd.read_sql('all_gzdata', engine, chunksize = 10000)

counts5 = [ i['fullURLId'][(i['fullURL'].str.contains('html'))==0].value_counts() for i in sql]#没有点击以html结尾的具体页面

counts5= pd.concat(counts5).groupby(level=0).sum()   

counts5 = pd.DataFrame(counts5)  

counts5['type'] = counts5.index.str.extract('(\d{3})') #提取前三个数字作为类别id

counts5_ = counts5[['type', 'fullURLId']].groupby('type').sum()#按类别合并

counts5_['ratio']=counts5_/counts5_.sum() #增加比例列

counts5_.sort_values('fullURLId', ascending = False) #按类型编码顺序排序  

#点击次数统计

sql = pd.read_sql('all_gzdata', engine, chunksize = 10000)

c = [i['realIP'].value_counts() for i in sql] #统计各个IP出现次数

count6 = pd.concat(c).groupby(level=0).sum()  #合并统计结果

count6 = pd.DataFrame(count6) #将Series转为DataFrame

count6[1] = 1 #添加一列全为1

count6_=count6.groupby('realIP').sum() #统计各个不同点击数 出现的次数

count6_['ratio1']=count6_[1]/count6_[1].sum()

count6_['ratio2']=count6_[1]*count6_.index/(count6_[1]*count6_.index).sum()

count6_.head(10)

可以看出80%的用户只提供了30%的浏览量,点击次数最大值为42790次,是律师浏览的信息。

数据预处理

1、clean合理删除数据

for i in sql:

  d = i[['realIP', 'fullURL']] #只要网址列

  d = d[d['fullURL'].str.contains('\.html')].copy() #只要含有.html的网址

  #保存到数据库的cleaned_gzdata表中(如果表不存在则自动创建)

  d.to_sql('cleaned_gzdata', engine, index = False, if_exists = 'append')

 

2、改变数据删除重复:由于用户在浏览网页时存在翻页情况,不同的网址属于同一类型的网页,针对这些网页需要还原其原始类别。

sql = pd.read_sql('cleaned_gzdata', engine, chunksize = 10000)

for i in sql: #逐块变换并去重

d = i.copy()

d['fullURL'] = d['fullURL'].str.replace('_\d{0,2}.html', '.html') #将下划线后面部分去掉,规范为标准网址

d = d.drop_duplicates() #删除重复记录

d.to_sql('changed_gzdata', engine, index = False, if_exists = 'append') #保存

3、分类目标是为用户提供个性化推荐,要进一步对数据进行分类

sql = pd.read_sql('changed_gzdata', engine, chunksize = 10000)

for i in sql: #逐块变换并去重

d = i.copy()

d['type_1'] = d['fullURL'] #复制一列

d['type_1'][d['fullURL'].str.contains('(ask)|(askzt)')] = 'zixun' #将含有ask、askzt关键字的网址的类别一归为咨询(后面的规则就不详细列出来了,实际问题自己添加即可)

d.to_sql('splited_gzdata', engine, index = False, if_exists = 'append') #保存

模型构建-具体参考链接网页

基于物品的协同过滤推荐、随机推荐、按照流行度推荐

基于物品的协同过滤推荐要分为两步:

1. 计算物品之间的相似度;

2. 根据物品相似度和用户的历史行为给用户生成推荐列表

由于用户行为是二元选择(0或者1),此处选择采用杰卡德相似系数法计算物品的相似度。

import numpy as np

def Jaccard(a, b): #自定义相似系数

  return 1.0*(a*b).sum()/(a+b-a*b).sum()

 

class Recommender():

  sim = None #相似度矩阵

  def similarity(self, x, distance): #计算相似度矩阵的函数

    y = np.ones((len(x), len(x)))

    for i in range(len(x)):

      for j in range(len(x)):

        y[i,j] = distance(x[i], x[j])

return y

 

  def fit(self, x, distance = Jaccard): #训练函数

    self.sim = self.similarity(x, distance)

 

  def recommend(self, a): #推荐函数

    return np.dot(self.sim, a)*(1-a)  

第13章 预测-财政收入影响因素分析及预测模型

目标

1) 梳理影响地方财政收入的关键特征,分析识别影响地方财政收入的关键特征的选择模型

2) 结合(1)的分析,对某市2015年财政总收入以及各个类别收入进行预测。

数据探索分析

影响财政收入(y)的因素很多,经查阅资料选以下因素为自变量

社会从业人数(x1)在岗职工工资总额(x2)社会消费品零售总额(x3)城镇居民人均可支配收入(x4)城镇居民人均消费性支出(x5)年末总人口(x6)全社会固定资产投入(x7)地区生产总值(x8)第一产业产值(x9)税收(x10)居民消费价格指数(x11)第三产业与第二产业产值比(x12)居民消费水平(x13)

描述性分析describe

inputfile = '../data/data1.csv' #输入的数据文件

data = pd.read_csv(inputfile) #读取数据

r = [data.min(), data.max(), data.mean(), data.std()] #依次计算最小值、最大值、均值、标准差

r = pd.DataFrame(r, index = ['Min', 'Max', 'Mean', 'STD']).T  #计算相关系数矩阵

np.round(r, 2) #保留两位小数

相关性分析data.corr(method='pearson'):x11与财政收入的线性关系不显著

数据预处理

#标准化处理
dataNM=(data-data.min())/(data.max()-data.min())

模型

变量选择模型lasso或者AdaptiveLasso

data = pd.read_csv( '../data/data1.csv') #读取数据

#导入AdaptiveLasso算法,要在较新的Scikit-Learn才有。

from sklearn.linear_model import AdaptiveLasso#import Lasso

model = AdaptiveLasso(gamma=1)##model=Lasso()

model.fit(data.iloc[:,0:13],data['y'])

q=model.coef_ #各个特征的系数

灰色预测与神经网络的组合模型
自定义GM11函数

#-*- coding: utf-8 -*-

 

def GM11(x0): #自定义灰色预测函数

import numpy as np

x1 = x0.cumsum() #1-AGO序列

z1 = (x1[:len(x1)-1] + x1[1:])/2.0 #紧邻均值(MEAN)生成序列

z1 = z1.reshape((len(z1),1))

B = np.append(-z1, np.ones_like(z1), axis = 1)

Yn = x0[1:].reshape((len(x0)-1, 1))

[[a],[b]] = np.dot(np.dot(np.linalg.inv(np.dot(B.T, B)), B.T), Yn) #计算参数

f = lambda k: (x0[0]-b/a)*np.exp(-a*(k-1))-(x0[0]-b/a)*np.exp(-a*(k-2)) #还原值

delta = np.abs(x0 - np.array([f(i) for i in range(1,len(x0)+1)]))

C = delta.std()/x0.std()

P = 1.0*(np.abs(delta - delta.mean()) < 0.6745*x0.std()).sum()/len(x0)

return f, a, b, x0[0], C, P #返回灰色预测函数、a、b、首项、方差比、小残差概率

灰色预测

from GM11 import GM11 #引入自己编写的灰色预测函数

 

inputfile = '../data/data1.csv' #输入的数据文件

outputfile = '../tmp/data1_GM11.xls' #灰色预测后保存的路径

data = pd.read_csv(inputfile) #读取一部分数据

data.index = range(1994, 2014)

data.loc[2014] = None

data.loc[2015] = None

l=['x1','x2','x3','x4','x5','x6','x7']

for i in l:

  f = GM11(data[i][np.arange(1994, 2014)].as_matrix())[0]#range改成np.arange,key错误

  data[i][2014] = f(len(data)-1) #2014年预测结果

  data[i][2015] = f(len(data)) #2015年预测结果

  data[i] = data[i].round(2) #保留两位小数

 

data[l+['y']].to_excel(outputfile) #结果输出

神经网络

#-*- coding: utf-8 -*-

import pandas as pd

inputfile = '../tmp/data1_GM11.xls' #灰色预测后保存的路径

outputfile = '../data/revenue.xls' #神经网络预测后保存的结果

modelfile = '../tmp/1-net.model' #模型保存路径

data = pd.read_excel(inputfile) #读取数据

feature = ['x1', 'x2', 'x3', 'x4', 'x5', 'x7'] #特征所在列

#统计

data_train = data.loc[range(1994,2014)].copy() #取2014年前的数据建模

data_mean = data_train.mean()

data_std = data_train.std()

data_train = (data_train - data_mean)/data_std #数据标准化

x_train = data_train[feature].as_matrix() #特征数据

y_train = data_train['y'].as_matrix() #标签数据

 

from keras.models import Sequential

from keras.layers.core import Dense, Activation

 

model = Sequential() #建立模型

model.add(Dense(12,input_dim=6))

model.add(Activation('relu')) #用relu函数作为激活函数,能够大幅提供准确度

model.add(Dense(1,input_dim=12))

model.compile(loss='mean_squared_error', optimizer='adam') #编译模型

model.fit(x_train, y_train, epochs = 10000, batch_size = 16) #训练模型,学习一万次

model.save_weights(modelfile) #保存模型参数

 

#预测,并还原结果。

x = ((data[feature] - data_mean[feature])/data_std[feature]).as_matrix()

data[u'y_pred'] = model.predict(x) * data_std['y'] + data_mean['y']#.tolist()

data.to_excel(outputfile)

 

import matplotlib.pyplot as plt #画出预测结果图

 

p = data[['y','y_pred']].plot(subplots = True, style=['b-o','r-*'])

plt.show()

第14章 层次聚类-基于基站定位数据的商圈分析

目标

1对用户的历史定位数据,采用数据挖掘技术,对基站进行分群

2对不同的商圈分群进行特征分析,比较不同商圈类别的价值,选择合适区域进行针对性的营销活动

探索分析

1、提取出基站范围内区域的人流特征:分类人流特征的四个指标,工作日上班时间人均停留时间、凌晨人均停留时间、周末人均停留时间和日均人流量。

2、由于各个属性之间的差异较大。为了消除数量级数据带来的影响,在聚类之前,需要进行离差标准化处理

data = (data - data.min())/(data.max() - data.min()) #离差标准化

模型-层次聚类

1、谱聚类

建模数据进行基于基站数据的商圈聚类,画出谱系聚类图

standardizedfile = '../data/standardized.xls' #标准化后的数据文件

data = pd.read_excel(standardizedfile, index_col = u'基站编号') #读取数据

 

import matplotlib.pyplot as plt

from scipy.cluster.hierarchy import linkage,dendrogram

#这里使用scipy的层次聚类函数

 

Z = linkage(data, method = 'ward', metric = 'euclidean') #谱系聚类图

P = dendrogram(Z, 0) #画谱系聚类图

plt.show()

2层次聚类

从图中可以看出,可以把聚类类别数取3类,再使用层次聚类算法进行训练模型

standardizedfile = '../data/standardized.xls' #标准化后的数据文件

k = 3 #聚类数

data = pd.read_excel(standardizedfile, index_col = u'基站编号') #读取数据

 

from sklearn.cluster import AgglomerativeClustering #导入sklearn的层次聚类函数

model = AgglomerativeClustering(n_clusters = k, linkage = 'ward')

model.fit(data) #训练模型

 

#详细输出原始数据及其类别

r = pd.concat([data, pd.Series(model.labels_, index = data.index)], axis = 1)  #详细输出每个样本对应的类别

r.columns = list(data.columns) + [u'聚类类别'] #重命名表头

 

import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei'] #用来正常显示中文标签

plt.rcParams['axes.unicode_minus'] = False #用来正常显示负号

 

style = ['ro-', 'go-', 'bo-']

xlabels = [u'工作日人均停留时间', u'凌晨人均停留时间', u'周末人均停留时间', u'日均人流量']

pic_output = '../tmp/type_' #聚类图文件名前缀

 

for i in range(k): #逐一作图,作出不同样式

  plt.figure()

  tmp = r[r[u'聚类类别'] == i].iloc[:,:4] #提取每一类

  for j in range(len(tmp)):

    plt.plot(range(1, 5), tmp.iloc[j], style[i])

  

  plt.xticks(range(1, 5), xlabels, rotation = 20) #坐标标签

  plt.title(u'商圈类别%s' %(i+1)) #我们计数习惯从1开始

  plt.subplots_adjust(bottom=0.15) #调整底部

  plt.savefig(u'%s%s.png' %(pic_output, i+1)) #保存图片

15章:电商产品评论数据情感分析代码详解目标

数据预处理

1抽取品牌是美的的数据

inputfile = '../data/huizong.csv' #评论汇总文件

outputfile = '../data/meidi_jd.txt' #评论提取后保存路径

data = pd.read_csv(inputfile, encoding = 'utf-8')

data = data[[u'评论']][data[u'品牌'] == u'美的']

data.to_csv(outputfile, index = False, header = False, encoding = 'utf-8')

 

2文本去重

inputfile = '../data/meidi_jd.txt' #评论文件

outputfile = '../data/meidi_jd_process_1.txt' #评论处理后保存路径

data = pd.read_csv(inputfile, encoding = 'utf-8', header = None,sep='\t')

l1 = len(data)

data = pd.DataFrame(data[0].unique())

l2 = len(data)

data.to_csv(outputfile, index = False, header = False, encoding = 'utf-8')

print(u'删除了%s条评论。' %(l1 - l2))

3把评论前面的评分删除

inputfile1 = '../data/meidi_jd_process_end_负面情感结果.txt'

outputfile1 = '../data/meidi_jd_neg.txt'

 

data1 = pd.read_csv(inputfile1, encoding = 'utf-8', header = None) #读入数据

data1 = pd.DataFrame(data1[0].str.replace('.*?\d+?\\t ', '')) #用正则表达式修改数据,删除平分负数

data1.to_csv(outputfile1, index = False, header = False, encoding = 'utf-8')

4结巴分词

inputfile1 = '../data/meidi_jd_neg.txt'

outputfile1 = '../data/meidi_jd_neg_cut.txt'

 

data1 = pd.read_csv(inputfile1, encoding = 'utf-8', header = None) #读入数据

mycut = lambda s: ' '.join(jieba.cut(s)) #自定义简单分词函数

data1 = data1[0].apply(mycut) #通过“广播”形式分词,加快速度。

模型-LDA

K-means是聚类的,他主要是处理数据的,对数据进行聚类。

LDA其实也是聚类的,主要是处理字符串的,对字符串进行聚类

 

#参数初始化

negfile = '../data/meidi_jd_neg_cut.txt'

posfile = '../data/meidi_jd_pos_cut.txt'

stoplist = '../data/stoplist.txt'

 

neg = pd.read_csv(negfile, encoding = 'utf-8', header = None) #读入数据

stop = pd.read_csv(stoplist, encoding = 'utf-8', header = None, sep = 'tipdm')

#sep设置分割词,由于csv默认以半角逗号为分割词,而该词恰好在停用词表中,因此会导致读取出错

#所以解决办法是手动设置一个不存在的分割词,如tipdm。

stop = [' ', ''] + list(stop[0]) #Pandas自动过滤了空格符,这里手动添加

 

neg[1] = neg[0].apply(lambda s: s.split(' ')) #定义一个分割函数,然后用apply广播

neg[2] = neg[1].apply(lambda x: [i for i in x if i not in stop]) #逐词判断是否停用词,思路同上

 

from gensim import corpora, models

 

#负面主题分析

neg_dict = corpora.Dictionary(neg[2]) #建立词典

neg_corpus = [neg_dict.doc2bow(i) for i in neg[2]] #建立语料库

neg_lda = models.LdaModel(neg_corpus, num_topics = 3, id2word = neg_dict) #LDA模型训练

for i in range(3):

  neg_lda.print_topic(i) #输出每个主题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值