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

一、导入关键包

# 导入数据分析需要的包
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.impute import KNNImputer
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

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

df=pd.read_csv('data/dataset.csv')


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

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

三、修改缺失值

3.1 查看缺失值

# 计算每列的缺失值数量
missing_values = df.isnull().sum()

# 绘制柱状图
plt.figure(figsize=(10, 6))
missing_values.plot(kind='bar')
plt.xlabel('Columns')
plt.ylabel('Missing Values Count')
plt.title('Missing Values in DataFrame')
plt.xticks(rotation=90)
plt.show()

在这里插入图片描述

3.1 众数

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

3.2 平均值

mean_values = df.mean()
print(mean_values)
df = df.fillna(mean_values)
print(df.isnull().sum())

3.3 中位数

median_values = df.median()
print(median_values)
df = df.fillna(median_values)
print(df.isnull().sum())

3.4 0填充

df = df.fillna(0)
print(df.isnull().sum())

3.5 KNN填充

KNNImputer的默认算法是基于K最近邻算法来填充缺失值。具体步骤如下:

  • 对于每个缺失值,找到其最近的K个邻居样本。
  • 使用这K个邻居样本的非缺失值来计算缺失值的近似值。可以使用均值、中位数或加权平均值等方法来计算近似值。
  • 将计算得到的近似值填充到缺失值的位置。
  • KNNImputer中的K值可以通过设置n_neighbors参数来指定,默认值为5。你也可以通过设置weights参数来选择不同的权重方式来计算近似值,默认为uniform,即所有邻居样本具有相同的权重。
# 导入数据集 'SERV_ID', ,"ACCT_MONTH"
df=pd.read_csv('data/dataset.csv')
# 查看数据
df.head(5)

# 定义 knnimputer
imputer = KNNImputer()
# 填充数据集中的空值
imputer.fit(df)     
# 转换数据集
Xtrans = imputer.transform(df)

# 打印转化后的数据集的空值
print('KNNImputer after Missing: %d' % sum(np.isnan(Xtrans).flatten()))
df_filled = pd.DataFrame(Xtrans, columns=df.columns)

四、修改异常值

4.1 删除

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

	your_dataframe.dropna(axis=0,how='all') 

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

	your_dataframe.dropna(axis=1,how='all') 

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

	your_dataframe.dropna(axis=0,how='any') 

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

  your_dataframe.dropna(axis=1,how='any')

4.2 替换

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

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

4.3 3σ原则

3σ原则,也称为三倍标准差原则,是统计学中一种常用的质量管理方法,用于判断数据是否偏离正常分布。其目标是通过计算数据的均值和标准差,确定异常值的存在,并将其排除或处理。也就是将连续型变量划入下图所示的八个区间中,完成离散化处理。以下是3σ原则的原理和步骤:

在这里插入图片描述

原理:

  • 假设数据集服从正态分布,根据正态分布的性质,大部分数据集中在均值附近,而异常值远离均值。
    根据3σ原则,大约68%的数据集中在均值的±1个标准差范围内,约95%的数据集中在均值的±2个标准差范围内,约99.7%的数据集中在均值的±3个标准差范围内。

步骤:

  1. 计算数据集的均值(μ)和标准差(σ)。
  2. 根据3σ原则,确定异常值的阈值范围。通常将均值加减3倍标准差作为阈值范围,即 μ±3σ。
  3. 遍历数据集,将落在阈值范围外的数据点标记为异常值。
  4. 根据业务需求,对异常值进行处理,可以选择删除、替换或其他处理方式。
  5. 重新分析处理后的数据集,确保异常值的影响被消除。

需要注意的是,3σ原则仅适用于符合正态分布假设的数据集。对于非正态分布的数据,可以考虑使用其他方法进行异常值检测和处理,如箱线图、Z分数等。

代码实现:

import pandas as pd
import numpy as np
def three_sigma(Ser):
    rule = (Ser.mean()-3*Ser.std()>Ser1) | (Ser.mean()+3*Ser.std()< Ser)
    index = np.arange(Ser1.shape[0])[rule]
    outrange = Ser.iloc[index]
    return outrange

4.4 箱型图

箱型图(Boxplot)也称箱须图(Box-whisker Plot)、盒式图或箱线图,是利用数据中的五个统计量:最小值、上四分位数、中位数、下四分位数与最大值来描述数据的一种统计图。它能够直观地显示数据的异常值,分布的离散程度以及数据的对称性。
在这里插入图片描述
在这里插入图片描述

中位数:数据按从小到大顺序排列后的处于中间位置的值,如果序列是偶数个,则是中间两个数的平均值;
下四分位数Q1:位于数据序列25%位置处的数;
上四分位数Q3:位于数据序列75%位置处的数;
四分位间距IQR:即 IQR = Q3-Q1;
下边缘:= Q1 – 1.5 *IQR;
上边缘:= Q3 + 1.5 *IQR;

代码实现:

def box_plot(index):
    # 使用自带的样式美化图片
    plt.style.use('ggplot')
    # 设置中文和负号正常显示
    plt.rcParams['font.sans-serif'] = 'Microsoft YaHei'
    plt.rcParams['axes.unicode_minus'] = False
    # 绘图:年龄箱线图
    plt.boxplot(x = df[index], # 指定绘图数据
                whis=1.5,#1.5倍的四分位值
                patch_artist=True, # 要求用自定义颜色填充盒形图,默认白色填充
                showmeans=True, # 以点的形式显示均值
                boxprops = {'color':'black','facecolor':'#9999ff'}, # 设置箱体属性,填充色和边框色
                flierprops = {'marker':'o','markerfacecolor':'red','color':'black'}, # 设置异常值属性,点的形状、填充色和边框色
                meanprops = {'marker':'D','markerfacecolor':'indianred'}, # 设置均值点的属性,点的形状、填充色
                medianprops = {'linestyle':'--','color':'orange'}) # 设置中位数线的属性,线的类型和颜色
    # 设置y轴的范围
    plt.ylim(0,85)
    # 去除箱线图的上边框与右边框的刻度标签
    plt.tick_params(top='off', right='off')
    # 显示图形
    plt.show()


# 导入数据集
df=pd.read_csv('data/dataset.csv')
# 查看数据
df.head(5)

numeric_cols=['ONLINE_LEN', 'SERV_ID_COUNT', 'CMPLNT_NUM', 'BANK_NUM','STOP_COUNT','CMPLNT_NUM']  #给出数值型特征的列名
for numeric_col in numeric_cols:
    box_plot(numeric_col)

在这里插入图片描述
在这里插入图片描述
异常值处理
对给定的某列Series进行异常值检测,并用不包括异常值的剩余数据的均值替换(Ser:进行异常值分析的DataFrame的某一列)

#定义箱线图识别异常值函数
def box_mean(Ser,Low=None,Up=None):
    if Low is None:
        Low=Ser.quantile(0.25)-1.5*(Ser.quantile(0.75)-Ser.quantile(0.25))
    if Up is None:
        Up=Ser.quantile(0.75)+1.5*(Ser.quantile(0.75)-Ser.quantile(0.25))
    Ser2=Ser[(Ser>=Low) & (Ser<=Up)]   #取出不包含异常点的数据,为了求均值
    Ser[(Ser<Low) | (Ser>Up)]=Ser2.mean()  #用非空且非异常数据的那些数据的均值替换异常值
    return(Ser)
   
cols=['ONLINE_LEN', 'SERV_ID_COUNT', 'CMPLNT_NUM', 'BANK_NUM','STOP_COUNT','CMPLNT_NUM']  #给出数值型特征的列名
for col_name in cols:
    data[col_name]=box_mean(data[col_name])

五、数据绘图分析

5.1 饼状图

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

# 查看总体客户流失情况
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 单特征与目标特征之间的图像

# 粘性/忠诚度分析  包括绑定银行卡张数
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)     # 设置坐标轴字体大小
# 从此表可知,对于没有绑定银行卡的用户流失情况会更大,应该加强督促用户绑定银行卡

在这里插入图片描述

# 查看正常用户与流失用户在上网流量上的差别
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 多特征与目标特征之间的图像

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

# 粘性/忠诚度分析  包括是否捆绑微信、是否捆绑支付宝
# 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)   # 设置坐标轴字体大小
# 从此表可知  支付宝绑定目前对于用户流失没有影响,微信的绑定影响会稍微大点,可能是微信用户用的较多

在这里插入图片描述

# 异常性 根据用户流失情况来结合判定
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.2.3 单特征的数值分布

plt.hist(df["policy_code"], bins=10)  # 设置直方图的箱数
plt.xlabel("policy_code")
plt.ylabel("Frequency")
plt.title("Distribution of policy_code" )
plt.show()

在这里插入图片描述

5.3 折线图

5.3.1 多个特征之间的关系图

# 用户的成长性分析,结合用户流失情况。
# 包括流量趋势、语音通话次数趋势、语音通话时长趋势、交往圈趋势
# 提取特征数据列
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 散点图

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"之间的关系。
在这里插入图片描述

5.5 绘图工具

工具一:只需要传入一个list列表,name表示绘图目标的名称(如损失图则为loss),color_index表示想要用哪一种颜色来绘图,save_path表示图片保存的位置

def plot_loss_curve(llist, name,color_index, save_path=None):
    colors = ["#0000ff",'#e4007f']
    plt.figure(figsize=(10, 5))

    freqs = [i for i in range(1, len(llist) + 1)]
    # 绘制训练损失变化曲线
    plt.plot(freqs, llist, color=colors[color_index], label="Train {}".format(name))

    # 绘制坐标轴和图例
    plt.ylabel("{}".format(name), fontsize='large')
    plt.xlabel("epoch", fontsize='large')
    plt.legend(loc='upper right', fontsize='x-large')
    plt.show()
    # plt.savefig("train_{}_curve.png".format(name))

六、特征选择

6.1、相关性分析

6.1.1 皮尔逊相关系数

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.1.2 斯皮尔曼相关系数

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.1.3 肯德尔相关系数

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.1.4 计算热力图

# 计算相关性矩阵
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()

6.2 主成分分析

PCA思想:构造原变量的一系列线性组合形成几个综合指标,以去除数据的相关性,并使低维数据最大程度保持原始高维数据的方差信息

一般来说在进行数据降维之前,需要先对其做归一化

from sklearn import preprocessing
from sklearn.decomposition import PCA
X_scaled = preprocessing. scale(X)
pca = PCA(n_components=6)       # 加载PCA算法,设置降维后主成分数目为2
# n_components的值不能大于n_features(特征数)和n_classes(类别数)之间的较小值减1。
reduced_x = pca.fit_transform(normalized_data)  # 对样本进行降维
reduced_x = pd.DataFrame(reduced_x, columns = ['pca_1','pca_2','pca_3','pca_4','pca_5','pca_6'])
reduced_x.head()

reduced_x.head()的结果
在这里插入图片描述

PCA代码:

# -*- coding:utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
from sklearn.decomposition import PCA           # 加载PCA算法包
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn import svm
import pandas as pd


df = pd.read_csv(r'D:\Python\test\iris.csv')
X = df.iloc[:, 0:4]
Y = df.iloc[:, 4]
x_train, x_test, y_train, y_test = train_test_split(X, Y, test_size=0.2, stratify=Y) # stratify 为分层抽样
pca = PCA(n_components=2)       # 加载PCA算法,设置降维后主成分数目为2
# n_components的值不能大于n_features(特征数)和n_classes(类别数)之间的较小值减1。
reduced_x = pca.fit_transform(X)  # 对样本进行降维
reduced_x = pd.DataFrame(reduced_x, columns = ['pca_1','pca_2'])
print(reduced_x.head(5))

# SVM分类
x_train, x_test, y_train, y_test = train_test_split(reduced_x, Y, test_size=0.2)
clf = svm.SVC(gamma='scale', decision_function_shape="ovr")    # 一对多法
# clf = svm.SVC(gamma='scale', decision_function_shape='ovo')  # 一对一法
clf.fit(x_train, y_train.astype('int'))
y_pred = clf.predict(x_test)


# 可视化,画分类结果图
N, M = 500, 500  # 横纵各采样多少个值
x1_min, x2_min = x_train.min(axis=0)
x1_max, x2_max = x_train.max(axis=0)
t1 = np.linspace(x1_min, x1_max, N)
t2 = np.linspace(x2_min, x2_max, M)
x1, x2 = np.meshgrid(t1, t2)  # 生成网格采样点
x_show = np.stack((x1.flat, x2.flat), axis=1)  # 测试点
y_predict = clf.predict(x_show)
cm_light = mpl.colors.ListedColormap(['#A0FFA0', '#FFA0A0', '#A0A0FF'])
cm_dark = mpl.colors.ListedColormap(['g', 'r', 'b'])
plt.pcolormesh(x1, x2, y_predict.reshape(x1.shape), cmap=cm_light)
plt.scatter(x_train.iloc[:, 0], x_train.iloc[:, 1], c=y_train, cmap=cm_dark, marker='o', edgecolors='k')
plt.grid(True, ls=':')
plt.show()

PCA结果:
在这里插入图片描述

6.3 线性判别分析

LDA思想:最早提出是为了解决生物问题的分类问题,有监督的线性降维。使用数据的类别信息,将高维的样本线性投影到低维空间中,使得数据样本在低维空间中,数据的类别区分度最大

LDA代码:

# 1.导入所需的库和模块:
import matplotlib.pyplot as plt
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
from sklearn.datasets import load_iris

# 2.加载数据集:
iris = load_iris()
X = iris.data
y = iris.target

# 3.创建一个LDA对象并拟合数据:
# 在这里,n_components参数指定要保留的主成分数量。
lda = LinearDiscriminantAnalysis(n_components=2)
X_lda = lda.fit_transform(X, y)

# 4.可以使用以下代码可视化结果:
plt.scatter(X_lda[:, 0], X_lda[:, 1], c=y)
plt.xlabel('LD1')
plt.ylabel('LD2')
plt.show()

LDA结果:
在这里插入图片描述
什么情况不适合做降维:

降维是将高维数据映射到低维空间的过程,以减少特征数量和复杂度。然而,并非所有情况下都适合进行降维,以下是一些不适合做降维的情况:

  • 数据维度本身较低:如果数据本身的维度已经很低,比如只有几个特征,那么进行降维可能会导致信息的丢失,反而不利于模型的建立和分析。
  • 数据特征之间的相关性较弱:如果数据特征之间的相关性较弱或者没有明显的相关关系,那么进行降维可能会导致信息的丢失,因为降维往往是基于特征之间的相关性来进行的。
  • 数据特征之间存在非线性关系:如果数据特征之间存在复杂的非线性关系,比如高阶相互作用或非线性映射,那么简单的降维方法(如主成分分析)可能无法捕捉到这些非线性关系,从而导致信息的丢失。
  • 数据中存在重要但难以捕捉的特征:有些特征可能在高维空间中对模型的性能有重要影响,但是在低维空间中很难被捕捉到。因此,在这种情况下,进行降维可能会导致模型性能的下降。

总的来说,降维可以帮助减少特征数量、简化模型、加快计算和可视化等,但并不是适用于所有情况。在决定是否进行降维时,需要综合考虑数据的维度、特征之间的相关性、非线性关系以及特征的重要性等因素,并根据具体问题和需求来做出决策。

七、数据归一化

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

  • 连续特征:一般采用归一标准化方式处理。
  • 离散特征:特征之间没有大小关系。
  • 离散特征:特征之间有大小关联,则采用数值映射。
# 通过归一化处理使特征数据标准为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()

八、模型搭建

# 深拷贝
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()]
]

九、模型训练

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代表模型的输出结果最差。

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模型

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

对于pkl模型

loaded_model = joblib.load('models/{}_model.pkl'.format(name))

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

# 由于没有预测数据集,选择最后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))
# 由于没有预测数据集,选择最后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))

在这里插入图片描述

十二、健康度分析

  • 参考链接----Python数据分析实战【十一】:学习用scorecardpy搭建风控评分卡模型【文末源码地址】

十三 模型融合-Stack

import warnings
warnings.filterwarnings('ignore')
import itertools
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
from sklearn import datasets
from sklearn.linear_model import LogisticRegression,ExtraTreesClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.naive_bayes import GaussianNB 
from sklearn.ensemble import RandomForestClassifier
from mlxtend.classifier import StackingClassifier
from sklearn.model_selection import cross_val_score, train_test_split
from mlxtend.plotting import plot_learning_curves
from mlxtend.plotting import plot_decision_regions


# 以python自带的鸢尾花数据集为例
iris = datasets.load_iris()
X, y = iris.data[:, 1:3], iris.target


clf1 = KNeighborsClassifier(n_neighbors=1)
clf2 = RandomForestClassifier(random_state=1)
clf3 = GaussianNB()
lr = LogisticRegression()
sclf = StackingClassifier(classifiers=[clf1, clf2, clf3], 
                          meta_classifier=lr)


label = ['KNN', 'Random Forest', 'Naive Bayes', 'Stacking Classifier']
clf_list = [clf1, clf2, clf3, sclf]
    
fig = plt.figure(figsize=(10,8))
gs = gridspec.GridSpec(2, 2)
grid = itertools.product([0,1],repeat=2)


clf_cv_mean = []
clf_cv_std = []
for clf, label, grd in zip(clf_list, label, grid):
        
    scores = cross_val_score(clf, X, y, cv=5, scoring='accuracy')
    print("Accuracy: %.2f (+/- %.2f) [%s]" %(scores.mean(), scores.std(), label))
    clf_cv_mean.append(scores.mean())
    clf_cv_std.append(scores.std())
        
    clf.fit(X, y)
    ax = plt.subplot(gs[grd[0], grd[1]])
    fig = plot_decision_regions(X=X, y=y, clf=clf)
    plt.title(label)


plt.show()

在这里插入图片描述

十四 模型融合-blending

# 以python自带的鸢尾花数据集为例
from sklearn.ensemble import ExtraTreesClassifier
data_0 = iris.data
data = data_0[:100,:]


target_0 = iris.target
target = target_0[:100]
 
#模型融合中基学习器
clfs = [LogisticRegression(),
        RandomForestClassifier(),
        ExtraTreesClassifier(),
        GradientBoostingClassifier()]
 
#切分一部分数据作为测试集
X, X_predict, y, y_predict = train_test_split(data, target, test_size=0.3, random_state=914)


#切分训练数据集为d1,d2两部分
X_d1, X_d2, y_d1, y_d2 = train_test_split(X, y, test_size=0.5, random_state=914)
dataset_d1 = np.zeros((X_d2.shape[0], len(clfs)))
dataset_d2 = np.zeros((X_predict.shape[0], len(clfs)))
 
for j, clf in enumerate(clfs):
    #依次训练各个单模型
    clf.fit(X_d1, y_d1)
    y_submission = clf.predict_proba(X_d2)[:, 1]
    dataset_d1[:, j] = y_submission
    #对于测试集,直接用这k个模型的预测值作为新的特征。
    dataset_d2[:, j] = clf.predict_proba(X_predict)[:, 1]
    print("val auc Score: %f" % roc_auc_score(y_predict, dataset_d2[:, j]))


#融合使用的模型
clf = GradientBoostingClassifier()
clf.fit(dataset_d1, y_d2)
y_submission = clf.predict_proba(dataset_d2)[:, 1]
print("Val auc Score of Blending: %f" % (roc_auc_score(y_predict, y_submission)))

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

ZZY_dl

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

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

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

打赏作者

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

抵扣说明:

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

余额充值