模型预测笔记(一):数据清洗及可视化、模型搭建、模型训练和预测代码一体化和对应结果展示(可作为baseline)

模型预测

一、导入关键包

python 复制代码
# 导入数据分析需要的包
import pandas as pd
import numpy as np
# 可视化包
import seaborn as sns
sns.set(style="whitegrid")
import matplotlib.pyplot as plt
%matplotlib inline
# 忽略警告信息
import warnings
warnings.filterwarnings('ignore')
# 导入数据分析需要的包
import pandas as pd
import numpy as np
from datetime import datetime

# 构建多个分类器
from sklearn.ensemble import RandomForestClassifier          # 随机森林
from sklearn.svm import SVC, LinearSVC                       # 支持向量机
from sklearn.linear_model import LogisticRegression          # 逻辑回归
from sklearn.neighbors import KNeighborsClassifier           # KNN算法
from sklearn.naive_bayes import GaussianNB                   # 朴素贝叶斯
from sklearn.tree import DecisionTreeClassifier              # 决策树分类器
from xgboost import XGBClassifier
from sklearn.ensemble import AdaBoostClassifier
from sklearn.ensemble import GradientBoostingClassifier   
from sklearn.metrics import precision_score, recall_score, f1_score
from sklearn.metrics import confusion_matrix
from sklearn.model_selection import GridSearchCV  # 网格搜索
np.set_printoptions(suppress=True)

# 显示中文
plt.rcParams["font.sans-serif"] = ["SimHei"]
plt.rcParams["axes.unicode_minus"] = False

二、如何载入、分析和保存文件

python 复制代码
df=pd.read_csv('data/dataset.csv')


df.head(5)# 查看前几列数据
df.tail() # 返回CSV文件的最后几行数据。
df.info() # 显示CSV文件的基本信息,包括数据类型、列数、行数、缺失值等。
df.describe()# 对CSV文件的数值型数据进行统计描述,包括计数、均值、标准差、最小值、最大值等。
df.shape()# 返回CSV文件的行数和列数。
df.unique()  # 返回CSV文件中某一列的唯一值。
df.value_counts()# 计算CSV文件中某一列中每个值的出现次数。
df.groupby() # 按照某一列的值进行分组,并对其他列进行聚合操作,如求和、计数、平均值等。
df.sort_values()# 按照某一列的值进行排序。
df.pivot_table()# 创建透视表,根据指定的行和列对数据进行汇总和分析。

# 保存处理后的数据集
3df.to_csv('data/Telecom_data_flag.csv')

三、修改缺失值

3.1 众数

python 复制代码
# 对每一列属性采用相应的缺失值处理方式,通过分析发现这类数据都可以采用众数的方式解决
df.isnull().sum()
modes = df.mode().iloc[0]
print(modes)
df = df.fillna(modes)
print(df.isnull().sum())

3.2 平均值

python 复制代码
mean_values = df.mean()
print(mean_values)
df = df.fillna(mean_values)
print(df.isnull().sum())

3.3 中位数

python 复制代码
median_values = df.median()
print(median_values)
df = df.fillna(median_values)
print(df.isnull().sum())

3.4 0填充

python 复制代码
df = df.fillna(0)
print(df.isnull().sum())

四、修改异常值

4.1 删除

1.删除DataFrame表中全部为NaN的行

python 复制代码
	your_dataframe.dropna(axis=0,how='all') 

2.删除DataFrame表中全部为NaN的列

python 复制代码
	your_dataframe.dropna(axis=1,how='all') 

3.删除表中含有任何NaN的行

python 复制代码
	your_dataframe.dropna(axis=0,how='any') 

4.删除表中含有任何NaN的列

python 复制代码
  your_dataframe.dropna(axis=1,how='any')

4.2 替换

这里的替换可以参考前文的中位数,平均值,众数,0替换等。

python 复制代码
	replace_value = 0.0
	# 这里设置 inplace 为 True,能够直接把表中的 NaN 值替换掉
	your_dataframe.fillna(replace_value, inplace=True)
	# 如果不设置 inplace,则这样写就行
	# new_dataframe = your_dataframe.fillna(replace_value)

五、数据绘图分析

5.1 饼状图

5.1.1 绘制某一特征的数值情况(二分类)

pyton 复制代码
# 查看总体客户流失情况
churnvalue = df["LEAVE_FLAG"].value_counts()
labels = df["LEAVE_FLAG"].value_counts().index
plt.pie(churnvalue,
        labels=["未流失","流失"],
        explode=(0.1,0),
        autopct='%.2f%%', 
        shadow=True,)
plt.title("客户流失率比例",size=24)
plt.show()
# 从饼形图中看出,流失客户占总客户数的很小的比例,流失率达3.58%

5.2 柱状图

5.2.1 单特征与目标特征之间的图像

python 复制代码
# 粘性/忠诚度分析  包括绑定银行卡张数
fig, axes = plt.subplots(1, 1, figsize=(12,12))
plt.subplot(1,1,1) 
# palette参数表示设置颜色
gender=sns.countplot(x='BANK_NUM',hue="LEAVE_FLAG",data=df,palette="Pastel2") 
plt.xlabel("绑定银行卡张数",fontsize=16)
plt.title("LEAVE_FLAG by BANK_NUM",fontsize=18)
plt.ylabel('count',fontsize=16)
plt.tick_params(labelsize=12)     # 设置坐标轴字体大小
# 从此表可知,对于没有绑定银行卡的用户流失情况会更大,应该加强督促用户绑定银行卡
python 复制代码
# 查看正常用户与流失用户在上网流量上的差别
plt.figure(figsize=(10,6))
g = sns.FacetGrid(data = df,hue = 'LEAVE_FLAG', height=4, aspect=3)
g.map(sns.distplot,'BYTE_ALL',norm_hist=True)
g.add_legend()
plt.ylabel('density',fontsize=16)
plt.xlabel('BYTE_ALL',fontsize=16)
plt.xlim(0, 100)
plt.tick_params(labelsize=13)     # 设置坐标轴字体大小
plt.tight_layout()
plt.show()
# 从上图看出,上网流量少的用户流失率相对较高。

5.2.2 多特征与目标特征之间的图像

这里绘制的多个二分类特征的情况是与目标特征之间的关系

python 复制代码
# 粘性/忠诚度分析  包括是否捆绑微信、是否捆绑支付宝
# sns.countplot()函数绘制了"是否使用支付宝"(IS_ZFB)这一列的柱状图,并根据"LEAVE_FLAG"(是否离网)进行了颜色分类。
fig, axes = plt.subplots(1, 2, figsize=(12,12))
plt.subplot(1,2,1) 
# palette参数表示设置颜色
partner=sns.countplot(x="IS_ZFB",hue="LEAVE_FLAG",data=df,palette="Pastel2")
plt.xlabel("是否使用支付宝(1代表使用,0代表使用)")
plt.title("LEAVE_FLAG by IS_ZFB",fontsize=18)
plt.ylabel('count',fontsize=16)
plt.tick_params(labelsize=12)   # 设置坐标轴字体大小

plt.subplot(1,2,2)
seniorcitizen=sns.countplot(x="IS_WX",hue="LEAVE_FLAG",data=df,palette="Pastel2")
plt.xlabel("是否使用微信(1代表使用,0代表使用)")
plt.title("LEAVE_FLAG by IS_WX",fontsize=18)
plt.ylabel('count',fontsize=16)
plt.tick_params(labelsize=12)   # 设置坐标轴字体大小
# 从此表可知  支付宝绑定目前对于用户流失没有影响,微信的绑定影响会稍微大点,可能是微信用户用的较多
python 复制代码
# 异常性 根据用户流失情况来结合判定
covariables=["CMPLNT_NUM", "STOP_COUNT"]
fig,axes=plt.subplots(1,2,figsize=(20,12))
for i, item in enumerate(covariables):
    '''
    0,'CMPLNT_NUM'
    1,'STOP_COUNT'
    '''
    plt.subplot(1,2,(i+1))
    ax=sns.countplot(x=item,hue="LEAVE_FLAG",data=df,palette="Set2")
    plt.xlabel(str(item),fontsize=16)
    plt.tick_params(labelsize=14)     # 设置坐标轴字体大小
    plt.title("LEAVE_FLAG by "+ str(item),fontsize=20)
    i=i+1
plt.tight_layout()
plt.show()
# 从此表可知 最近6个月累计投诉次数间接性的决定了用户的流失,停机天数也和用户流失成正相关。

5.3 折线图

5.3.1 多个特征之间的关系图

python 复制代码
# 用户的成长性分析,结合用户流失情况。
# 包括流量趋势、语音通话次数趋势、语音通话时长趋势、交往圈趋势
# 提取特征数据列
feature1 = df["LIULIANG_B"]
feature2 = df["YUYING_COUNT"]
feature3 = df["YUYING_B"]
feature4 = df["JIAOWANG_B"]

# 绘制折线图
plt.plot(feature1, label="LIULIANG_B")
plt.plot(feature2, label="YUYING_COUNT")
plt.plot(feature3, label="YUYING_B")
plt.plot(feature4, label="JIAOWANG_B")

# 添加标题和标签
plt.title("Trend of User growth")
plt.xlabel("Index")
plt.ylabel("Value")

# 添加图例
plt.legend()

# 显示图表
plt.show()
# 从此图可以发现针对流量趋势来说,用户的波动是最大的。

5.4 散点图

python 复制代码
df.plot(x="SERV_ID_COUNT", y="CDR_NUM", kind="scatter", c="red")
plt.show()

这段代码的作用是绘制一个以"SERV_ID_COUNT"为横轴,"CDR_NUM"为纵轴的散点图,并将散点的颜色设置为红色。通过这个散点图,可以直观地观察到"SERV_ID_COUNT"和"CDR_NUM"之间的关系。

六、相关性分析

6.1 皮尔逊相关系数

python 复制代码
plt.figure(figsize=(16,8))
df.corr()['LEAVE_FLAG'].sort_values(ascending = False).plot(kind='bar')
plt.tick_params(labelsize=14)     # 设置坐标轴字体大小
plt.xticks(rotation=45)         # 设置x轴文字转向
plt.title("Correlations between LEAVE_FLAG and variables",fontsize=20)
plt.show()
# 从图可以直观看出,YUYING_COUNT 、YUYING_B、IS_ZFB、BALANCE、JIAOWANG_B、IS_WX这六个变量与LEAVE_FLAG目标变量相关性最弱。

6.2 斯皮尔曼相关系数

python 复制代码
plt.figure(figsize=(16,8))
df.corr(method='spearman')['LEAVE_FLAG'].sort_values(ascending = False).plot(kind='bar')
plt.tick_params(labelsize=14)     # 设置坐标轴字体大小
plt.xticks(rotation=45)         # 设置x轴文字转向
plt.title("Correlations between LEAVE_FLAG and variables",fontsize=20)
plt.show()

6.3 肯德尔相关系数

python 复制代码
plt.figure(figsize=(16,8))
df.corr(method='kendall')['LEAVE_FLAG'].sort_values(ascending = False).plot(kind='bar')
plt.tick_params(labelsize=14)     # 设置坐标轴字体大小
plt.xticks(rotation=45)         # 设置x轴文字转向
plt.title("Correlations between LEAVE_FLAG and variables",fontsize=20)
plt.show()

6.4 计算热力图

python 复制代码
# 计算相关性矩阵
corr_matrix = df.corr()

# 绘制热力图
plt.figure(figsize=(10, 8))
sns.heatmap(corr_matrix, annot=True, cmap="coolwarm")
plt.title("Correlation Heatmap", fontsize=16)
plt.show()

七、数据归一化

特征主要分为连续特征和离散特征,其中离散特征根据特征之间是否有大小关系又细分为两类。

  • 连续特征:一般采用归一标准化方式处理。
  • 离散特征:特征之间没有大小关系。
  • 离散特征:特征之间有大小关联,则采用数值映射。
python 复制代码
# 通过归一化处理使特征数据标准为1,均值为0,符合标准的正态分布,
# 降低数值特征过大对预测结果的影响
# 除了目标特征全部做归一化,目标特征不用做,归一化会导致预测结果的解释变得困难
from sklearn.preprocessing import StandardScaler  
# 实例化一个转换器类
scaler = StandardScaler(copy=False)
target = df["LEAVE_FLAG"]
# 提取除目标特征外的其他特征
other_features = df.drop("LEAVE_FLAG", axis=1)
# 对其他特征进行归一化
normalized_features = scaler.fit_transform(other_features)
# 将归一化后的特征和目标特征重新组合成DataFrame
normalized_data = pd.DataFrame(normalized_features, columns=other_features.columns)
normalized_data["LEAVE_FLAG"] = target
normalized_data.head()

八、模型搭建

python 复制代码
# 深拷贝
X=normalized_data.copy()
X.drop(['LEAVE_FLAG'],axis=1, inplace=True)
y=df["LEAVE_FLAG"]
#查看预处理后的数据
X.head()

# 建立训练数据集和测试数据集
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size = 0.3, random_state = 0)
print("原始训练集包含样本数量: ", len(X_train))
print("原始测试集包含样本数量:  ", len(X_test))
print("原始样本总数: ", len(X_train)+len(X_test))

# 使用分类算法 
Classifiers=[
            ["RandomForest",RandomForestClassifier()],
            ["LogisticRegression",LogisticRegression(C=1000.0, random_state=30, solver="lbfgs",max_iter=100000)],
            ["NaiveBayes",GaussianNB()],
            ["DecisionTree",DecisionTreeClassifier()],
            ["AdaBoostClassifier", AdaBoostClassifier()],
            ["GradientBoostingClassifier", GradientBoostingClassifier()],
            ["XGB", XGBClassifier()]
]

九、模型训练

python 复制代码
from datetime import datetime
import pickle
import joblib

def get_current_time():
    current_time = datetime.now()
    formatted_time = current_time.strftime("%Y-%m-%d %H:%M:%S")
    return current_time, formatted_time

Classify_result=[]
names=[]
prediction=[]
i = 0

for name, classifier in Classifiers:
    start_time, formatted_time = get_current_time()
    print("**********************************************************************")
    print("第{}个模型训练开始时间:{}  模型名称为:{}".format(i+1, formatted_time, name))
    classifier = classifier
    classifier.fit(X_train, y_train)
    y_pred = classifier.predict(X_test)
    recall = recall_score(y_test, y_pred)
    precision = precision_score(y_test, y_pred)
    f1score = f1_score(y_test, y_pred)
    model_path = 'models/{}_{}_model.pkl'.format(name, round(precision, 5))
    print("开始保存模型文件路径为:{}".format(model_path))
    # 保存模型方式1
    #     with open('models/{}_{}_model.pkl'.format(name, precision), 'wb') as file:
    #         pickle.dump(classifier, file)
    #     file.close()
    # 保存模型方式2
    joblib.dump(classifier, model_path)
    
    end_time = datetime.now()  # 获取训练结束时间
    print("第{}个模型训练结束时间:{}".format(i+1, end_time.strftime("%Y-%m-%d %H:%M:%S")))
    print("训练耗时:", end_time - start_time)

    # 打印训练过程中的指标
    print("Classifier:", name)
    print("Recall:", recall)
    print("Precision:", precision)
    print("F1 Score:", f1score)
    print("**********************************************************************")
    
    # 保存指标结果
    class_eva = pd.DataFrame([recall, precision, f1score])
    Classify_result.append(class_eva)
    
    name = pd.Series(name)
    names.append(name)
    
    y_pred = pd.Series(y_pred)
    prediction.append(y_pred)
    
    i += 1

十、评估模型

召回率(recall)的含义是:原本为对的当中,预测为对的比例(值越大越好,1为理想状态)

精确率、精度(precision)的含义是:预测为对的当中,原本为对的比例(值越大越好,1为理想状态)

F1分数(F1-Score)指标综合了Precision与Recall的产出的结果

F1-Score的取值范围从0到1的,1代表模型的输出最好,0代表模型的输出结果最差。

python 复制代码
classifier_names=pd.DataFrame(names)
# 转成列表
classifier_names=classifier_names[0].tolist()
result=pd.concat(Classify_result,axis=1)
result.columns=classifier_names
result.index=["recall","precision","f1score"]
result

十一、预测模型

对于h5模型

python 复制代码
from keras.models import load_model
model = load_model('lstm_model.h5')
pred = model.predict(X, verbose=0)
print(pred)

对于pkl模型

python 复制代码
loaded_model = joblib.load('models/{}_model.pkl'.format(name))

由于没有预测数据集,选择最后n条数为例进行预测。

python 复制代码
# 由于没有预测数据集,选择最后n条数为例进行预测。
n = 500
pred_id = SERV_ID.tail(n)
# 提取预测数据集特征(如果有预测数据集,可以一并进行数据清洗和特征提取)
pred_x = X.tail(n)

# 使用上述得到的最优模型
model = GradientBoostingClassifier()

model.fit(X_train,y_train)
pred_y = model.predict(pred_x) # 预测值

# 预测结果
predDf = pd.DataFrame({'SERV_ID':pred_id, 'LEAVE_FLAG':pred_y})
print("*********************原始的标签情况*********************")
print(df.tail(n)['LEAVE_FLAG'].value_counts())
print("*********************预测的标签情况*********************")
print(predDf['LEAVE_FLAG'].value_counts())
print("*********************预测的准确率*********************")
min1 = min(df.tail(n)['LEAVE_FLAG'].value_counts()[0],predDf['LEAVE_FLAG'].value_counts()[0])
min2 = min(df.tail(n)['LEAVE_FLAG'].value_counts()[1],predDf['LEAVE_FLAG'].value_counts()[1])
print("{}%".format(round((min1+min2)/n,3)*100))
python 复制代码
# 由于没有预测数据集,选择最后n条数为例进行预测。
n = 500 # 预测的数量
pred_id = SERV_ID.tail(n)
# 提取预测数据集特征(如果有预测数据集,可以一并进行数据清洗和特征提取)
pred_x = X.tail(n)
# 加载模型
loaded_model = joblib.load('models/GradientBoostingClassifier_0.77852_model.pkl')
# 使用加载的模型进行预测
pred_y = loaded_model.predict(pred_x)
# 预测结果
predDf = pd.DataFrame({'SERV_ID':pred_id, 'LEAVE_FLAG':pred_y})
print("*********************原始的标签情况*********************")
print(df.tail(n)['LEAVE_FLAG'].value_counts())
print("*********************预测的标签情况*********************")
print(predDf['LEAVE_FLAG'].value_counts())
print("*********************预测的准确率*********************")
min1 = min(df.tail(n)['LEAVE_FLAG'].value_counts()[0],predDf['LEAVE_FLAG'].value_counts()[0])
min2 = min(df.tail(n)['LEAVE_FLAG'].value_counts()[1],predDf['LEAVE_FLAG'].value_counts()[1])
print("{}%".format(round((min1+min2)/n,3)*100))
相关推荐
Li_RuiQi14 小时前
DAgger方法演进_独立学习笔记
笔记·学习·计算机视觉
Li_RuiQi18 小时前
DAgger与交互式模仿学习_ACT学习笔记
笔记·学习
He BianGu18 小时前
【笔记】C# 中BindingFlags的详细作用
笔记·c#
AI视觉网奇19 小时前
turtle 入门教程笔记
笔记
跨知易知识产权19 小时前
美国专利确权是什么,和专利诉讼有什么不一样?
笔记
杨逢昌工厂6S管理19 小时前
126-杨逢昌6S三环体系:越做越乱的现场熵增机理与基准化治理——一线现场诊断笔记
经验分享·笔记·职场和发展·学习方法
悟道书生19 小时前
若依 RBAC 权限控制学习笔记
java·网络·笔记·sql·学习·vue
陈哈哈111120 小时前
折腾了半天,总算把 Vim 9.2 装明白了
笔记
陈哈哈111120 小时前
折腾了半天,总算把 OpenGL 的开发环境给装明白了
笔记
深圳老胡21 小时前
STM32F103 硬件 SPI 与软件 IO 模拟 SPI 最高速度差异详解
笔记·stm32·单片机·代码规范·1024程序员节