一.标准化
二.归一化
三.二值化
四.独热编码与标签编码
一.标准化
1.什么是标准化?
标准化指的是将数据按比例缩放,使之落入一个小的特定区间。在大多数情况下,这个区间是[0, 1],但有时也可以是[-1, 1]。标准化后的数据的平均值为0,标准差为1。
标准化通常使用以下公式进行:
z=(x−μ)/σ
其中,x是原始数据,μ是数据的均值,σ是数据的标准差,z是标准化后的数据。
目的:使不同特征具有相同的尺度,便于算法处理
在机器学习中,标准化数据时应使用训练集的统计信息来处理所有数据集(包括验证集和测试集),以避免数据泄漏并保持一致性。
2.案例
案例1:(方法一:手搓)将"[[1,2,3,4],[9,8,7,6],[11,12,11,44]]"该组数据标准化
import pandas as pd
data=pd.DataFrame([[1,2,3,4],[9,8,7,6],[11,12,11,44]])
column=["特征1","特征2","特征3","特征4"]
index=["数据1","数据2","数据3"]
data.columns=column
data.index=index
print(data)
data_mean=data.mean() #每一列特征的平均值
data_std=data.std() #每一列特征的标准差
data1=data-data_mean
data2=data1/data_std #标准化后的数据
print(data2.round(2))
特征1 特征2 特征3 特征4
数据1 1 2 3 4
数据2 9 8 7 6
数据3 11 12 11 44
特征1 特征2 特征3 特征4
数据1 -1.13 -1.06 -1.0 -0.62
数据2 0.38 0.13 0.0 -0.53
数据3 0.76 0.93 1.0 1.15
案例1:(方法二:调用sklearn库)将"[[1,2,3,4],[9,8,7,6],[11,12,11,44],[10,10,10,10]]"该组数据标准化
import pandas as pd
from sklearn.preprocessing import StandardScaler
#数据导入
data=pd.DataFrame([[1,2,3,4],[9,8,7,6],[11,12,11,44],[10,10,10,10]])
column=["特征1","特征2","特征3","特征4"]
index=["数据1","数据2","数据3","数据4"]
data.columns=column
data.index=index
print(data)
#创建标准化实例,训练集与测试集的划分
scaler=StandardScaler()
x_train=data[:3]
x_test=data[3:4]
#计算x_train的均值与标准差,并保存统计信息
scaler.fit(x_train)
#使用保存的统计信息,来标准化x_train,x_text,data
order_train=scaler.transform(x_train)
order_test=scaler.transform(x_test)
order_data=scaler.transform(data)
#输出标准化后的order_train,order_test,order_data
print("标准化后的训练集:\n",order_train.round(2))
print("标准化后的测试集:\n",order_test.round(2))
print("标准化后的原数据:\n",order_data.round(2))
#打印出原数据的均值与标准差,既在调用fit方法时存储下来的
print("标准化前原数据的均值:",scaler.mean_.round(2)) #均值
print("标准化前原数据的标准差:",scaler.scale_.round(2)) #标准差
print("标准化后数据的均值:",order_data.mean(axis=0).round(2))
print("标准化后数据的标准差:",order_data.std(axis=0).round(2))
特征1 特征2 特征3 特征4
数据1 1 2 3 4
数据2 9 8 7 6
数据3 11 12 11 44
数据4 10 10 10 10
标准化后的训练集:
[[-1.39 -1.3 -1.22 -0.76]
[ 0.46 0.16 0. -0.65]
[ 0.93 1.14 1.22 1.41]]
标准化后的测试集:
[[ 0.69 0.65 0.92 -0.43]]
标准化后的原数据:
[[-1.39 -1.3 -1.22 -0.76]
[ 0.46 0.16 0. -0.65]
[ 0.93 1.14 1.22 1.41]
[ 0.69 0.65 0.92 -0.43]]
标准化前原数据的均值: [ 7. 7.33 7. 18. ]
标准化前原数据的标准差: [ 4.32 4.11 3.27 18.4 ]
标准化后数据的均值: [ 0.17 0.16 0.23 -0.11]
标准化后数据的标准差: [0.92 0.91 0.95 0.89]
二.归一化
1.什么是归一化?
归一化是将数据按比例缩放,以使其落入一个指定的最小到最大值的范围内。最常见的归一化范围是 [0, 1]。
归一化通常使用以下公式进行:
x′=(x−x_min)/(x_max−x_min)
其中,x是原始数据,x_min是数据的最小值,x_max是数据的最大值,x′是归一化后的数据。
目的:防止不同量纲的特征对模型结果产生过大影响
2.案例
案例1:(调用sklearn库)
import numpy as np
import pandas as pd
from sklearn.preprocessing import MinMaxScaler
data=pd.DataFrame([
[25,175,79,0],
[21,169,75,1],
[22,155,72,0]])
print(data)
#创建归一化实例
mms=MinMaxScaler((0,1))#括号里的参数改为取值范围
#计算最大值最小值,并进行归一化处理
new_data=pd.DataFrame(mms.fit_transform(data))
print(new_data)
#预测
text_data=np.array([21,122,73,1]).reshape(1,-1)
print(mms.transform(text_data))
#反推
try_data=np.array([1,1,1,1]).reshape(1,-1)
print(mms.inverse_transform(try_data))
0 1 2 3
0 25 175 79 0
1 21 169 75 1
2 22 155 72 0
0 1 2 3
0 1.00 1.0 1.000000 0.0
1 0.00 0.7 0.428571 1.0
2 0.25 0.0 0.000000 0.0
[[ 0. -1.65 0.14285714 1. ]]
[[ 25. 175. 79. 1.]]
三.二值化
1.什么是二值化?
二值化(Binarization)是数据预处理中的一种技术,它将数据转换为仅包含两个值的数据,通常是0和1。这种转换通常基于一个阈值,数据点根据是否超过这个阈值被分类为0或1。二值化在各种应用中都很有用,特别是在特征工程中,当需要将连续变量转换为分类变量时。
公式:
x是原始数据,t是阈值,x′是二值化后的数据。
目的:简化数据,将连续变量转换为离散变量。
2.案例
案例1(方法1:手搓)
import numpy as np
data=np.array([
[20,30,40,50],
[10,29,405,60],
[30,406,406,30]
],dtype="float32")
#法一
new_data=data.copy()
new_data=np.where(new_data>=45,1,0)
print(new_data)
"""
法二:
new_data[new_data>=45]=1
new_data[new_data<=45]=0
"""
[[0 0 0 1]
[0 0 1 1]
[0 1 1 0]]
案例1(方法2:调用sklearn库)
from sklearn.preprocessing import Binarizer
import numpy as np
data=np.array([
[20,30,40,50],
[10,29,405,60],
[30,406,406,30]
],dtype="float32")
#创建二值化实例,并设置阈值为50
bin=Binarizer(threshold=50)#大于阈值
#进行二值化
new_data=bin.fit_transform(data)
print(new_data)
[[0. 0. 0. 0.]
[0. 0. 1. 1.]
[0. 1. 1. 0.]]
四.编码类别特征
1.独热编码
1.什么是独热编码?
独热编码(One-Hot Encoding)是一种处理分类数据的常用技术,特别是在机器学习中。它将分类变量的不同类别转换为二进制(0或1)的形式,每个类别对应一个唯一的二进制向量。这种编码方式使得机器学习算法能够更好地理解和处理分类数据,尤其是那些处理数值数据的算法.
设有数据为:
3 4 5
3 2 5
1 3 4
独热编码:每一列特征用不同的二进制表示,数位的个数为每一列的不同值数量
3:10 4:100 5:10
1:01 2:010 4:01
3:001
编码后
10 100 10
10 010 10
01 001 01
2.案例
案例1:(方法1:手搓)
import numpy as np
data=np.array([1,2,3,4,5,8,7,5,3,1,3,3]).reshape(-1,3)
print(data)
c_data=data.copy()
list=[]
for col in data.T:
dict={}
for val in col:
dict[val]=None
list.append(dict)#利用字典的去重性
print(list)
for dict in list:
size=len(dict)
for index,key in enumerate(sorted(dict.keys())):
dict[key]=np.zeros(shape=size,dtype=int)
dict[key][index]=1
print(list)
list1=[]
for d in c_data:
new_list=np.array([],dtype=int)
for index,key in enumerate(d):
new_list=np.hstack((new_list,list[index][key]))
list1.append(new_list)
list1=np.array(list1)
print(list1)
[[1 2 3]
[4 5 8]
[7 5 3]
[1 3 3]]
[{1: None, 4: None, 7: None}, {2: None, 5: None, 3: None}, {3: None, 8: None}]
[{1: array([1, 0, 0]), 4: array([0, 1, 0]), 7: array([0, 0, 1])}, {2: array([1, 0, 0]), 5: array([0, 0, 1]), 3: array([0, 1, 0])}, {3: array([1, 0]), 8: array([0, 1])}]
[[1 0 0 1 0 0 1 0]
[0 1 0 0 0 1 0 1]
[0 0 1 0 0 1 1 0]
[1 0 0 0 1 0 1 0]]
案例1:(方法2:调用sklearn库)
from sklearn.preprocessing import OneHotEncoder
import numpy as np
data=np.array([1,2,3,4,5,8,7,5,3,1,3,3]).reshape(-1,3)
print(data)
#创建独热编码器
ohe=OneHotEncoder(sparse_output=False,dtype=int)
#计算独热编码
new_data=ohe.fit_transform(data)#先拟合后转换
print(new_data)
#反向解码
test_array=np.array([0,1,0,0,0,1,1,0]).reshape(1,-1)
try_=ohe.inverse_transform(test_array)
print(try_)
[[1 2 3]
[4 5 8]
[7 5 3]
[1 3 3]]
[[1 0 0 1 0 0 1 0]
[0 1 0 0 0 1 0 1]
[0 0 1 0 0 1 1 0]
[1 0 0 0 1 0 1 0]]
[[4 5 3]]
2.标签编码
1.什么是标签编码?
标签编码(Label Encoding)是一种将分类变量转换为整数的方法,通常用于将类别标签转换为从0开始的整数序列。这种方法在处理不平衡数据集时特别有用,因为它可以确保每个类别的权重相等。标签编码适用于有序特征,其中类别之间存在一定的顺序关系,但没有明确的意义
2.案例
案例1(方法1:调用sklearn库)
import numpy as np
from sklearn.preprocessing import LabelEncoder
data=np.array(["wo","we","w","ew","r","wo"])
#创建标签编码实例
lbe=LabelEncoder()
#计算,将每个标签用,从0开始的整数代替
data_=lbe.fit_transform(data)
print(data_)
#反向编码
da=[2,0,1]
da_=lbe.inverse_transform(da)
print(da_)
#使用原训练集的结果,进行编码,前提是所要编码的标签已被创建成功,不然会找不到数字进行代替,而出现保存
st="w we"
st_=st.split(" ")
print(st_)
st__=lbe.transform(st_)
print(st__)
[4 3 2 0 1 4]
['w' 'ew' 'r']
['w', 'we']
[2 3]
五.特征工程-1逐步回归
#1.导入必要的库
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import statsmodels.api as sm
from sklearn.datasets import make_regression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, r2_score
from sklearn.preprocessing import StandardScaler
#2.设置显示选项
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
pd.set_option('display.max_rows', None) #显示最大行数
pd.set_option('display.max_columns', None) #显示最大列数
pd.set_option('display.max_colwidth', None) #显示的最大列宽
pd.set_option('display.width', None) #显示的最宽度
#3.导入数据
data=pd.read_excel("客户价值数据表.xlsx")
x=data.drop(["客户价值"],axis=1) #去掉"客户价值这一列"
y=data["客户价值"]
#4.数据预处理
#4.1标准化
scaler = StandardScaler()
x=scaler.fit_transform(x)
x=pd.DataFrame(x,columns=["历史贷款金额","贷款次数","学历","月收入","性别"])
#4.2划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=42)
#5.建立模型
def stepwise_selection(X, y, initial_list=[], threshold_in=0.01, threshold_out=0.05, verbose=True):
"""
逐步回归特征选择
:param X: 特征数据(DataFrame)
:param y: 目标变量(Series)
:param initial_list: 初始特征列表
:param threshold_in: 添加特征的显著性阈值
:param threshold_out: 删除特征的显著性阈值
:param verbose: 是否打印过程
:return: 最终选择的特征列表
"""
included = list(initial_list)
while True:
changed = False
# 前向选择
excluded = list(set(X.columns) - set(included))
new_pval = pd.Series(index=excluded, dtype=float)
for new_column in excluded:
model = sm.OLS(y, sm.add_constant(pd.DataFrame(X[included + [new_column]]))).fit()
new_pval[new_column] = model.pvalues[new_column]
best_pval = new_pval.min()
if best_pval < threshold_in:
best_feature = new_pval.idxmin()
included.append(best_feature)
changed = True
if verbose:
print(f"Add {best_feature} with p-value {best_pval:.6f}")
# 后向消除
model = sm.OLS(y, sm.add_constant(pd.DataFrame(X[included]))).fit()
pvalues = model.pvalues.iloc[1:] # 忽略截距
worst_pval = pvalues.max()
if worst_pval > threshold_out:
changed = True
worst_feature = pvalues.idxmax()
included.remove(worst_feature)
if verbose:
print(f"Remove {worst_feature} with p-value {worst_pval:.6f}")
if not changed:
break
return included
# 运行逐步回归
selected_features = stepwise_selection(X_train, y_train)
# 输出最终选择的特征
print("最终选择的特征:", selected_features)
六.特征工程-2PCA主成分分析
主成分分析(Principal Component Analysis, PCA) 是一种常用的降维技术,通过线性变换将高维数据映射到低维空间,同时保留数据的主要信息。PCA 的目标是找到数据中方差最大的方向(主成分),并用这些方向来表示数据。
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
import numpy as np
# 1. 标准化数据
scaler = StandardScaler()
data_scaled = scaler.fit_transform(data)
# 2. 使用 PCA 降维
pca = PCA(n_components=2) # 降维到 2 维
data_reduced = pca.fit_transform(data_scaled)
# 3. 输出结果
print("降维后的数据:\n", data_reduced)
print("解释方差比:\n", pca.explained_variance_ratio_)
七.特征工程-3随机森林特征重要性
#1.导入必备的库
import pandas as pd
import numpy as np
from matplotlib import pyplot as plt
from scipy import stats
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import train_test_split, GridSearchCV, cross_val_score, KFold
from sklearn.metrics import mean_squared_error, r2_score
from sklearn.preprocessing import StandardScaler
#2.设置显示选项
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
pd.set_option('display.max_rows', None) #显示最大行数
pd.set_option('display.max_columns', None) #显示最大列数
pd.set_option('display.max_colwidth', None) #显示的最大列宽
pd.set_option('display.width', None) #显示的最宽度
#3.导入数据
data=pd.read_excel("信用评分卡模型.xlsx")
#4.数据预处理
#4.1使用均值填写缺失值
print("缺失值统计:\n",data.isnull().sum())
data=data.apply(lambda col:col.fillna(col.mean()),axis=0)
#4.2处理异常值
numeric_data = data.select_dtypes(include=[np.number])
z_scores = np.abs(stats.zscore(data.select_dtypes(include=[np.number]))) # 仅对数值型数据计算 Z-score
threshold = 3 # Z-score 阈值 3个标准差
outliers = (z_scores > threshold).any(axis=1) # 检测异常值
print("检测到的异常值行索引:\n", data[outliers].index.tolist()) # 输出异常值的行索引
print(data[outliers])
data = data[~outliers] # 移除异常值
X=data.drop("信用评分",axis=1)
y=data["信用评分"]
#4.3将数据划分为训练集与测试集
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.3,random_state=0)
#4.4创建标准化训练测试集与训练集
scaler=StandardScaler()
X_train=scaler.fit_transform(X_train)
X_test=scaler.transform(X_test)
#5.建立模型
Model = RandomForestRegressor(
criterion='squared_error', # 分裂标准(MSE)
min_samples_leaf=2, # 叶节点所需的最小样本数
bootstrap=True, # 使用 Bootstrap 采样
oob_score=True, # 使用袋外样本评估模型性能
random_state=42, # 固定随机种子
n_jobs=-1, # 使用所有 CPU 核心
# verbose=1 # 输出训练进度
)
#5.1参数调优:网格搜索(数据量大时使用随机搜索)
cv = KFold(n_splits=5, shuffle=True, random_state=42)
param_grid = {
'n_estimators': [50, 100, 200], # 树的数量
'max_depth': [None, 5, 10], # 树的最大深度
'min_samples_split': [2, 5], # 分裂内部节点所需的最小样本数
'max_features': ['sqrt', 'log2'] # 每棵树分裂时考虑的特征数
}
grid_search = GridSearchCV(
estimator=Model,
param_grid=param_grid,
cv = cv, # 5折交叉验证
scoring='neg_mean_squared_error', # 负均方误差(越大越好)
n_jobs=-1, # 使用所有CPU核心
)
grid_search.fit(X_train, y_train)
print("最佳参数组合:", grid_search.best_params_)
best_model = grid_search.best_estimator_
#5.2模型评估
cv_scores = cross_val_score(best_model, X_train, y_train,cv=cv, scoring='neg_mean_squared_error')
print(f"交叉验证 MSE: {-np.mean(cv_scores):.4f} (±{np.std(cv_scores):.4f})")
y_pred = best_model.predict(X_test)
mse = mean_squared_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)
print(f"测试集 MSE: {mse:.4f}")
print(f"测试集 R²: {r2:.4f}")
#5.3模型特征重要性
feature_importances = pd.DataFrame(best_model.feature_importances_, index=X.columns)
feature_importances = feature_importances.sort_values(by=0,ascending=False)
print("\n特征重要性:")
print(feature_importances)
#6.可视化
plt.figure()
feature_importances.plot(kind='barh')
plt.title("Feature Importances")
plt.show()
八.模型选择
#1.导入必备的库
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from statsmodels.stats.outliers_influence import variance_inflation_factor
from sklearn.feature_selection import mutual_info_regression
#2.显示选项
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
"""
1.皮尔逊相关系数:用于衡量两个连续变量之间的线性关系,值范围在 -1 到 1 之间。
值接近 1 表示强正相关,接近 -1 表示强负相关,接近 0 表示无相关性。
2.斯皮尔曼等级相关系数:用于衡量两个变量之间的单调关系,适用于非正态分布的数据。
3.肯德尔相关系数:另一种用于衡量两个变量之间的相关性的方法,适用于小样本数据。
"""
df=pd.read_excel("客户价值数据表.xlsx")
pearson = df.corr(method='pearson') # 计算皮尔逊相关系数
spearman =df.corr(method='spearman') # 计算斯皮尔曼等级相关系数
kendall = df.corr(method='kendall') # 计算肯德尔相关系数
correlation_matrices = [pearson, spearman, kendall]
names = ["pearson", "spearman", "kendall"]
# 遍历列表并绘制热力图
for matrix, name in zip(correlation_matrices, names):
plt.figure(figsize=(10, 8))
sns.heatmap(matrix, annot=True, fmt=".2f", cmap='coolwarm')
plt.title(f"{name}相关性矩阵")
plt.show()
#2.VIF 用于检测多重共线性,计算每个特征与其他特征的相关性。VIF 值越高,表示该特征与其他特征的相关性越强,通常 VIF > 10 被认为存在严重的多重共线性
# 计算 VIF
X = df.drop('客户价值', axis=1) # 特征
vif = pd.DataFrame()
vif['特征'] = X.columns
vif['VIF'] = [variance_inflation_factor(X.values, i) for i in range(X.shape[1])]
print(vif)
# 互信息用于衡量两个变量之间的信息共享程度,适用于分类和连续变量。值越高,表示两个变量之间的相关性越强。
y=df["客户价值"]
mi = mutual_info_regression(X, y)
mi_scores = pd.Series(mi, index=X.columns)
print(mi_scores.sort_values(ascending=False))