机器学习--数据清洗—(续篇)
本文摘要: 该代码实现了矿物数据分类的完整机器学习流程。首先对原始数据进行预处理,包括删除异常类别、缺失值检测、标签编码和Z标准化。然后采用随机森林算法进行缺失值填充,通过训练集数据预测并填充测试集缺失值。接着使用SMOTE算法解决样本不均衡问题,并保存处理后的数据集。最后实现了6种分类算法(逻辑回归、随机森林、SVM、AdaBoost、朴素贝叶斯和XGBoost)进行矿物类型预测,通过网格搜索优
一·随机森林的算法填充
import pandas as pd
import matplotlib.pyplot as plt
import fill_data
data = pd.read_excel("矿物数据.xls")
data = data[data['矿物类型'] != 'E'] # 删除特殊的类别E。整个数据集中只存在1个E数据。
null_num = data.isnull()
null_total = null_num.sum() # 检测每列中的缺失值
X_whole = data.drop('矿物类型', axis=1).drop('序号', axis=1) # 获取全部特征数据
y_whole = data.矿物类型 # 获取全部标签数据
label_dict = {"A": 0, "B": 1, "C": 2, "D": 3} # 将数据中的中文标签转换为字符
encoded_labels = [label_dict[label] for label in y_whole]
y_whole = pd.Series(encoded_labels, name='矿物类型') # 将列表转换为Pandas Series
# 数据中存在大量字符串数值、\、空格等异常数据。字符串数值直接转换为float,\和空格转换为nan
for column_name in X_whole.columns:
X_whole[column_name] = pd.to_numeric(X_whole[column_name], errors='coerce')
#pd.to_numeric()函数尝试将参数中的数据转换为数值类型。如果转换失败,它会引发一个异常,
#设置errors='coerce',会将无法转换的值设置为NaN。
"""数据标准化:Z标准化"""
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_whole_Z = scaler.fit_transform(X_whole)
X_whole = pd.DataFrame(X_whole_Z, columns=X_whole.columns) # Z标准化处理后为numpy数据,这里再转换回pandas数据
'''数据集的切分'''
from sklearn.model_selection import train_test_split
x_train_w, x_test_w, y_train_w, y_test_w = \
train_test_split(X_whole, y_whole, test_size=0.3, random_state=50000)
'''数据中存在空缺,进行6种方法进行填充'''
## 1、只保留完整数据集
# x_train_fill,y_train_fill = fill_data.cca_train_fill(x_train_w,y_train_w)#调用自己写的implement_data.py
# 测试集的填充
# x_test_fill,y_test_fill = fill_data.cca_test_fill(x_train_fill, y_train_fill, x_test_w, y_test_w)#调用
#2、使用平均值的方法对数据进行填充
# x_train_fill,y_train_fill = fill_data.mean_train_fill(x_train_w,y_train_w)
# 测试集的填充
# x_test_fill,y_test_fill = fill_data.mean_test_fill(x_train_fill, y_train_fill, x_test_w, y_test_w)
##3、使用中位数的方法对数据进行填充
# x_train_fill,y_train_fill = fill_data.median_train_fill(x_train_w,y_train_w)#调用自己写的implement_data
##测试集的填充
# x_test_fill,y_test_fill = fill_data.median_test_fill(x_train_fill, y_train_fill, x_test_w, y_test_w)
##4、使用众数的方法对数据进行填充
# x_train_fill,y_train_fill = fill_data.mode_train_fill(x_train_w,y_train_w)#调用自己写的implement_data.p
###测试集的填充
# x_test_fill,y_test_fill = fill_data.mode_test_fill(x_train_fill, y_train_fill, x_test_w, y_test_w)#调
# 5、线性回归算法实现训练数据集、测试数据集的填充
x_train_fill,y_train_fill = fill_data.lr_train_fill(x_train_w,y_train_w)#调用自己写的#implement_data.py文
# 测试集的填充
#x_test_fill,y_test_fill = fill_data.lr_test_fill(x_train_fill, y_train_fill, x_test_w, y_test_w)#调用自
## 6、随机森林算法实现训练数据集、测试数据集的填充
x_train_fill,y_train_fill = fill_data.rf_train_fill(x_train_w,y_train_w)
# 测试集的填充
x_test_fill,y_test_fill = fill_data.rf_test_fill(x_train_fill, y_train_fill, x_test_w, y_test_w)#调用自己
'''smote算法实现数据集的拟合,解决样本不均衡'''
from imblearn.over_sampling import SMOTE
oversampler = SMOTE(k_neighbors=1, random_state=42)#数据对象
os_x_train, os_y_train = oversampler.fit_resample(x_train_fill, y_train_fill)#人工拟合的只是训练集。
'''数据保存为excel文件'''
data_train = pd.concat([os_y_train,os_x_train],axis=1).sample(frac=1, random_state=4)#sample()方法用于从 `DataFrame` 中随机抽取行,`frac` 表示抽取行的比例。
data_test = pd.concat([y_test_fill,x_test_fill],axis=1)#测试集不用传入模型训练,无需打乱顺序。
data_train.to_excel(r'.//temp_data//训练数据集[平均值填充的数据].xlsx', index=False)
data_test.to_excel(r'.//temp_data//测试数据集[平均值填充的数据].xlsx', index=False)
from sklearn.ensemble import RandomForestRegressor
'''---------------------随机森林算法实现训练数据集、测试数据集的填充---------------------'''
def rf_train_fill(train_data, train_label):
'''使用随机森林算法填充训练数据集中的缺失值'''
train_data_all = pd.concat([train_data, train_label], axis=1)
train_data_all = train_data_all.reset_index(drop=True)#data数据行号存在混乱(因随机抽取70%的数据作为训练集导致),进行重置
train_data_X = train_data_all.drop('矿物类型', axis=1)
null_num = train_data_X.isnull().sum() # 查看每个特征中存在空数据的个数
null_num_sorted = null_num.sort_values(ascending=True)#将空数据的类别从小到大进行排序
filling_feature = []
for i in null_num_sorted.index:
filling_feature.append(i)
if null_num_sorted[i] !=0:
X = train_data_X[filling_feature].drop(i, axis=1)
y = train_data_X[i]
row_numbers_mg_null = train_data_X[train_data_X[i].isnull()].index.tolist()#获取空数据对应行号
X_train = X.drop(row_numbers_mg_null) # 非空的数据作为训练数据集
y_train = y.drop(row_numbers_mg_null) # 非空的标签作为训练标签
X_test = X.iloc[row_numbers_mg_null] # 空的数据作为测试数据集
regr = RandomForestRegressor(n_estimators=100, random_state=42) # 创建随机森林回归模型
regr.fit(X_train, y_train) # 训练模型
y_pred = regr.predict(X_test) # 使用模型进行预测
train_data_X.loc[row_numbers_mg_null,i] = y_pred#loc和iloc的区别:iloc[行号.列号] loc[行名,列名],例如iloc[3,4]
print('完成训练数据集中的\'{}\'列数据的填充'.format(i))
return train_data_X, train_data_all.矿物类型
def rf_test_fill(train_data, train_label, test_data, test_label):
'''使用随机森林算法对测试数据集中缺失的数据进行填充,主要是基于这样一个思想:
根据已经填充后的训练数据集建立模型,来补充空缺的测试数据集。'''
train_data_all = pd.concat([train_data, train_label], axis=1)
train_data_all = train_data_all.reset_index(drop=True)
test_data_all = pd.concat([test_data, test_label], axis=1)
test_data_all = test_data_all.reset_index(drop=True)
train_data_X = train_data_all.drop('矿物类型', axis=1)
test_data_X = test_data_all.drop('矿物类型', axis=1)
null_num = test_data_X.isnull().sum()
null_num_sorted = null_num.sort_values(ascending=True)
filling_feature = []
for i in null_num_sorted.index:
filling_feature.append(i)
if null_num_sorted[i] !=0:
X_train = train_data_X[filling_feature].drop(i, axis=1)
y_train = train_data_X[i]
X_test = test_data_X[filling_feature].drop(i, axis=1)
row_numbers_mg_null = test_data_X[test_data_X[i].isnull()].index.tolist()#获取空数据对应行号
X_test = X_test.iloc[row_numbers_mg_null] # 空的数据作为测试数据集
regr = RandomForestRegressor(n_estimators=100, random_state=42) # 创建随机森林回归模型
regr.fit(X_train, y_train) # 训练模型
y_pred = regr.predict(X_test) # 使用模型进行预测
test_data_X.loc[row_numbers_mg_null,i] = y_pred
print('完成测试数据集中的\'{}\'列数据的填充'.format(i))
return test_data_X, test_data_all.矿物类型
rf_train_fill 函数(训练集填充)
python
运行
from sklearn.ensemble import RandomForestRegressor
- 导入随机森林回归器,用于构建预测缺失值的模型(因为缺失值是连续数值,所以用回归而非分类)
python
运行
'''---------------------随机森林算法实现训练数据集、测试数据集的填充---------------------'''
def rf_train_fill(train_data, train_label):
- 定义
rf_train_fill函数,参数是训练特征(train_data,对应整体代码中的x_train_w)和训练标签(train_label,对应y_train_w) - 功能:用随机森林填充训练集中的缺失值,返回填充后的训练特征和标签
python
运行
train_data_all = pd.concat([train_data, train_label], axis=1)
- 合并训练特征和标签(按列合并,
axis=1),得到包含特征 + 标签的完整训练数据 - 原因:后续填充时可能需要保持特征与标签的对应关系(虽然填充逻辑中未直接用标签,但保留完整结构更安全)
python
运行
train_data_all = train_data_all.reset_index(drop=True)
- 重置数据的索引(
drop=True表示删除原有索引,不保留为新列) - 原因:之前用
train_test_split划分数据集时,索引可能被打乱(不是连续的 0,1,2...),重置后方便后续按行索引操作
python
运行
train_data_X = train_data_all.drop('矿物类型', axis=1)
- 从合并数据中删除标签列(
矿物类型),得到纯特征数据(train_data_X) - 因为填充操作只针对特征,不涉及标签
python
运行
null_num = train_data_X.isnull().sum()
- 统计每个特征列的缺失值数量(
isnull()判断是否为 NaN,sum()按列求和) - 例如:若某列有 10 个 NaN,
null_num中该列对应的值就是 10
python
运行
null_num_sorted = null_num.sort_values(ascending=True)
- 对缺失值数量按升序排序(
ascending=True) - 核心逻辑:先处理缺失值少的特征(用其他更完整的特征预测它),再处理缺失值多的特征(避免用已填充过的、误差可能较大的特征做过多预测)
python
运行
filling_feature = []
- 创建空列表,用于记录 “已经处理过的特征”
- 作用:后续用这些已处理的特征作为输入,预测当前需要填充的特征
python
运行
for i in null_num_sorted.index:
- 遍历排序后的特征名称(按缺失值从少到多的顺序)
python
运行
filling_feature.append(i)
- 将当前遍历的特征加入 “已处理列表”
- 即使该特征没有缺失值,也会加入(作为后续其他特征的预测输入)
python
运行
if null_num_sorted[i] !=0:
- 只处理有缺失值的特征(无缺失值的特征跳过填充逻辑)
python
运行
X = train_data_X[filling_feature].drop(i, axis=1)
- 构建 “预测输入特征集”:从已处理的特征中,去掉当前要填充的特征
i - 例如:当前填充特征是
Fe,已处理特征有SiO2、Al2O3、Fe,则X就是SiO2和Al2O3的数据(用它们预测Fe的缺失值)
python
运行
y = train_data_X[i]
- 定义 “预测目标”:当前要填充的特征
i的所有值(包括非缺失和缺失的)
python
运行
row_numbers_mg_null = train_data_X[train_data_X[i].isnull()].index.tolist()
- 找到特征
i中所有缺失值所在的行索引,并转为列表 - 例如:
Fe列在第 5、10、15 行有缺失,则这个列表就是[5,10,15]
python
运行
X_train = X.drop(row_numbers_mg_null)
- 构建模型的训练输入:从
X中删除缺失值所在的行(只保留特征i非缺失的行) - 这些行的特征
i有真实值,可用于训练模型
python
运行
y_train = y.drop(row_numbers_mg_null)
- 构建模型的训练目标:从
y中删除缺失值所在的行(只保留特征i的非缺失值)
python
运行
X_test = X.iloc[row_numbers_mg_null]
- 构建模型的测试输入:从
X中提取缺失值所在的行(这些行的特征i需要被预测填充)
python
运行
regr = RandomForestRegressor(n_estimators=100, random_state=42)
- 创建随机森林回归模型:
n_estimators=100表示用 100 棵树,random_state=42固定随机种子(保证结果可复现)
python
运行
regr.fit(X_train, y_train)
- 用非缺失数据训练模型:学习输入特征
X_train与目标y_train(特征i的真实值)的关系
python
运行
y_pred = regr.predict(X_test)
- 预测缺失值:用训练好的模型,对缺失行的输入特征
X_test进行预测,得到特征i缺失值的预测结果
python
运行
train_data_X.loc[row_numbers_mg_null,i] = y_pred
- 填充缺失值:将预测结果
y_pred赋值给特征i的缺失行(通过行索引定位) loc按 “行索引 + 列名” 定位,确保准确填充到缺失位置
python
运行
print('完成训练数据集中的\'{}\'列数据的填充'.format(i))
- 打印日志:提示当前特征
i的填充已完
python
运行
return train_data_X, train_data_all.矿物类型
- 函数返回:填充后的训练特征(
train_data_X)和对应的标签(train_data_all.矿物类型) - 对应整体代码中接收的
x_train_fill, y_train_fill
rf_test_fill 函数(测试集填充)
python
运行
def rf_test_fill(train_data, train_label, test_data, test_label):
- 定义
rf_test_fill函数,参数包括:填充后的训练特征(train_data)、训练标签(train_label)、原始测试特征(test_data,对应x_test_w)、测试标签(test_label,对应y_test_w) - 功能:用训练集的数据训练模型,填充测试集中的缺失值,返回填充后的测试特征和标签
python
运行
train_data_all = pd.concat([train_data, train_label], axis=1)
train_data_all = train_data_all.reset_index(drop=True)
- 合并填充后的训练特征和标签,重置索引(同训练集填充逻辑,统一格式)
python
运行
test_data_all = pd.concat([test_data, test_label], axis=1)
test_data_all = test_data_all.reset_index(drop=True)
- 合并原始测试特征和标签,重置索引(处理测试集的索引混乱问题)
python
运行
train_data_X = train_data_all.drop('矿物类型', axis=1)
test_data_X = test_data_all.drop('矿物类型', axis=1)
- 从合并数据中分离出训练集特征(
train_data_X)和测试集特征(test_data_X)(均删除标签列)
python
运行
null_num = test_data_X.isnull().sum()
null_num_sorted = null_num.sort_values(ascending=True)
- 统计测试集每个特征的缺失值数量,并按升序排序(同训练集逻辑,先处理缺失少的)
python
运行
filling_feature = []
for i in null_num_sorted.index:
filling_feature.append(i)
if null_num_sorted[i] !=0:
- 逻辑同训练集:创建 “已处理特征列表”,遍历测试集特征(按缺失值从少到多),只处理有缺失值的特征
python
运行
X_train = train_data_X[filling_feature].drop(i, axis=1)
- 构建模型的训练输入:使用训练集的已处理特征(而非测试集自身),去掉当前要填充的特征
i - 核心:测试集填充的模型完全基于训练集,避免数据泄露(测试集信息不能参与模型训练)
python
运行
y_train = train_data_X[i]
- 构建模型的训练目标:训练集中特征
i的所有值(此时训练集已填充完整,无缺失)
python
运行
X_test = test_data_X[filling_feature].drop(i, axis=1)
row_numbers_mg_null = test_data_X[test_data_X[i].isnull()].index.tolist()
X_test = X_test.iloc[row_numbers_mg_null]
- 构建模型的测试输入:从测试集的已处理特征中,提取当前特征
i缺失值所在行的数据(用于预测填充)
python
运行
regr = RandomForestRegressor(n_estimators=100, random_state=42)
regr.fit(X_train, y_train)
y_pred = regr.predict(X_test)
test_data_X.loc[row_numbers_mg_null,i] = y_pred
print('完成测试数据集中的\'{}\'列数据的填充'.format(i))
- 逻辑同训练集:用训练集数据训练模型,预测测试集缺失值并填充,打印日志
python
运行
return test_data_X, test_data_all.矿物类型
二·模型算法
一·算法--逻辑回归
- 函数返回:填充后的测试特征(
test_data_X)和对应的标签(test_data_all.矿物类型) - 对应整体代码中接收的
x_test_fill, y_test_fill
import pandas as pd
from sklearn import metrics
# 数据提取
train_data = pd.read_excel(r'./temp_data/训练数据集[平均值填充的数据].xlsx')
train_data_x = train_data.iloc[:, 1:] # 训练数据集的特征
train_data_y = train_data.iloc[:, 0] # 训练数据集的测试标签label
test_data = pd.read_excel(r'./temp_data/测试数据集[平均值填充的数据].xlsx')
test_data_x = test_data.iloc[:, 1:] # 测试数据集的特征
test_data_y = test_data.iloc[:, 0] # 测试数据集的测试标签label
result_data = {} # 用来保存后面6种算法的结果
'''#####################逻辑回归LR算法实现代码###########################'''
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import GridSearchCV # 网格搜索
param_grid = {
'penalty': ['l1', 'l2', 'elasticnet', 'none'], # 正则化类型
'C': [0.001, 0.01, 0.1, 1, 10, 100], # 正则化强度的倒数
'solver': ['newton-cg', 'lbfgs', 'liblinear', 'sag', 'saga'], # 优化算法
'max_iter': [100, 200, 500], # 最大迭代次数
'multi_class': ['auto', 'ovr', 'multinomial'],
} # 多分类策略(注意: 'none' 惩罚时不支持 'multinomial')
# 注意: 'penalty' 为 'none' 时, 'C' 将被忽略。而且, 不是所有的求解器都支持所有的正则化选项。
# 另外, 当使用 'liblinear' 求解器时, 'multi_class' 只能为 'ovr'。
# 因此, 在实际使用中, 可能需要针对特定的求解器调整参数网格。
# 注意: 上述参数网格在实际应用中可能需要调整, 因为某些参数组合可能不支持·或不稳定。
# 例如, 当使用L1正则化时, 'solver' 参数就不能使用 'newton-cg', 'sag' 和 'lbfgs'。
# 同样地, 当 'penalty' 是 'none' 时, 'C' 参数将不起作用。
# 创建Logistic回归模型实例
logreg = LogisticRegression()
grid_search = GridSearchCV(logreg, param_grid, cv=5) # 创建GridSearchCV对象
grid_search.fit(train_data_x, train_data_y) # 在训练集上执行网格搜索
print("Best parameters set found on development set:") # 输出最佳参数
print(grid_search.best_params_)
...
"""建立最优模型"""
LR_result = {} # 用来保存训练之后的结果。
lr = LogisticRegression(C=0.001, max_iter=100, penalty='none', solver='newton-cg') # 逻辑回归的参
lr.fit(train_data_x, train_data_y)
'''测试结果【含训练数据集的测试 + 测试数据集的测试】'''
train_predicted = lr.predict(train_data_x) # 训练数据集的预测结果
print('LR的train:\n', metrics.classification_report(train_data_y, train_predicted))
test_predicted = lr.predict(test_data_x) # 测试数据集的预测结果
print('LR的test:\n', metrics.classification_report(test_data_y, test_predicted)) # 打印测试数据集的
a = metrics.classification_report(test_data_y, test_predicted, digits=6) # digits表示保留有效位数
b = a.split()
LR_result['recall_0'] = float(b[6]) # 添加类别为0的召回率
LR_result['recall_1'] = float(b[11]) # 添加类别为1的召回率
LR_result['recall_2'] = float(b[16]) # 添加类别为2的召回率
LR_result['recall_3'] = float(b[21]) # 添加类别为3的召回率
LR_result['acc'] = float(b[25]) # 添加accuracy的结果
result_data['LR'] = LR_result # result_data是总体的结果,
print('lr结束')
分别确立确立特征x和y标签
import pandas as pd
from sklearn import metrics
# 数据提取
train_data = pd.read_excel(r'./temp_data/训练数据集[平均值填充的数据].xlsx')
train_data_x = train_data.iloc[:, 1:] # 训练数据集的特征
train_data_y = train_data.iloc[:, 0] # 训练数据集的测试标签label
test_data = pd.read_excel(r'./temp_data/测试数据集[平均值填充的数据].xlsx')
test_data_x = test_data.iloc[:, 1:] # 测试数据集的特征
test_data_y = test_data.iloc[:, 0] # 测试数据集的测试标签label

result_data = {} # 用来保存后面6种算法的结果
网格搜索——核心还是交叉验证
from sklearn.model_selection import GridSearchCV # 网格搜索
param_grid = {
'penalty': ['l1', 'l2', 'elasticnet', 'none'], # 正则化类型
'C': [0.001, 0.01, 0.1, 1, 10, 100], # 正则化强度的倒数
'solver': ['newton-cg', 'lbfgs', 'liblinear', 'sag', 'saga'], # 优化算法
'max_iter': [100, 200, 500], # 最大迭代次数
'multi_class': ['auto', 'ovr', 'multinomial'],
}
# 多分类策略(注意: 'none' 惩罚时不支持 'multinomial')
# 注意: 'penalty' 为 'none' 时, 'C' 将被忽略。而且, 不是所有的求解器都支持所有的正则化选项。
# 另外, 当使用 'liblinear' 求解器时, 'multi_class' 只能为 'ovr'。
# 因此, 在实际使用中, 可能需要针对特定的求解器调整参数网格。
# 注意: 上述参数网格在实际应用中可能需要调整, 因为某些参数组合可能不支持·或不稳定。
# 例如, 当使用L1正则化时, 'solver' 参数就不能使用 'newton-cg', 'sag' 和 'lbfgs'。
# 同样地, 当 'penalty' 是 'none' 时, 'C' 参数将不起作用。
logreg = LogisticRegression()
grid_search = GridSearchCV(logreg, param_grid, cv=5) # 创建GridSearchCV对象
grid_search.fit(train_data_x, train_data_y) # 在训练集上执行网格搜索
print("Best parameters set found on development set:") # 输出最佳参数
print(grid_search.best_params_)
logreg = LogisticRegression()
得到一个逻辑回归对象
grid_search = GridSearchCV(logreg, param_grid, cv=5) # 创建GridSearchCV对象
然后参数进行网格交换实验,
GridSearchCV网格搜索算法内部就是交叉验证
C参数是惩罚因子
"""建立最优模型"""
LR_result = {} # 用来保存训练之后的结果。
lr = LogisticRegression(C=0.001, max_iter=100, penalty='none', solver='newton-cg') # 逻辑回归的参
lr.fit(train_data_x, train_data_y)
lr = LogisticRegression(C=0.001, max_iter=100, penalty='none', solver='newton-cg') # 逻辑回归的参
这里就是把之前网络搜索的内容给填进来,
'''测试结果【含训练数据集的测试 + 测试数据集的测试】'''
train_predicted = lr.predict(train_data_x) # 训练数据集的预测结果
print('LR的train:\n', metrics.classification_report(train_data_y, train_predicted))
test_predicted = lr.predict(test_data_x) # 测试数据集的预测结果
print('LR的test:\n', metrics.classification_report(test_data_y, test_predicted)) # 打印测试数据集的
a = metrics.classification_report(test_data_y, test_predicted, digits=6) # digits表示保留有效位数
b = a.split()
分别把预测集的y和测试集的y打印出来,然后比较
LR_result['recall_0'] = float(b[6]) # 添加类别为0的召回率
LR_result['recall_1'] = float(b[11]) # 添加类别为1的召回率
LR_result['recall_2'] = float(b[16]) # 添加类别为2的召回率
LR_result['recall_3'] = float(b[21]) # 添加类别为3的召回率
LR_result['acc'] = float(b[25]) # 添加accuracy的结果
result_data['LR'] = LR_result # result_data是总体的结果,
print('lr结束')


输入字典表格,返回到这个位置来
LR_result = {} # 用来保存训练之后的结果。
然后保存训练好预测数据
二·算法--随机森林
'''#####################RF算法实现代码###########################'''
from sklearn.ensemble import RandomForestClassifier
# from sklearn.model_selection import GridSearchCV
#定义网络参数
# param_grid = {
# 'n_estimators': [50, 100, 200], # 树的数量
# 'max_depth': [None, 10, 20, 30], # 树的深度
# 'min_samples_split': [2, 5, 10], # 节点分裂所需的最小样本数
# 'min_samples_leaf': [1, 2, 5], # 叶子节点所需的最小样本数
# 'max_features': ['auto', 'sqrt', 'log2'], # 最大特征数
# 'bootstrap': [True, False] # 是否使用自举样本
# }
# ## 创建RandomForest分类器实例
# # rf = RandomForestClassifier()
#
# ## 创建GridSearchCV对象
# # grid_search = GridSearchCV(rf, param_grid, cv=5)
#
# ## 在训练集上执行网格搜索
# # grid_search.fit(train_data_x, train_data_y)
#
# ## 输出最佳参数
# # print("Best parameters set found on development set:")
# # print()
# # print(grid_search.best_params_)
RF_result = {}
rf = RandomForestClassifier(bootstrap=False,
max_depth=20,
max_features='log2',
min_samples_leaf=1,
min_samples_split=2,
n_estimators=50,
random_state=487)
rf.fit(train_data_x, train_data_y)
train_predicted = rf.predict(train_data_x) # 训练数据集的预测结果
test_predicted = rf.predict(test_data_x) # 测试数据集的预测结果
print('RF的train:\n', metrics.classification_report(train_data_y, train_predicted)) # 打印训练数据集的
print('RF的test:\n', metrics.classification_report(test_data_y, test_predicted)) # 打印测试数据集
rf_test_report = metrics.classification_report(test_data_y, test_predicted, digits=6)
b = rf_test_report.split()
RF_result['recall_0'] = float(b[6]) # 添加类别为0的召回率
RF_result['recall_1'] = float(b[11]) # 添加类别为1的召回率
RF_result['recall_2'] = float(b[16]) # 添加类别为2的召回率
RF_result['recall_3'] = float(b[21]) # 添加类别为3的召回率
RF_result['acc'] = float(b[25]) # 添加accuracy的结果
result_data['RF'] = RF_result
这段代码实现了使用随机森林(Random Forest)算法进行分类任务,并对模型性能进行了评估。让我逐步解释代码的主要功能和流程:
-
导入必要的库
python
运行
from sklearn.ensemble import RandomForestClassifier这里导入了 scikit-learn 库中的随机森林分类器。
-
参数网格(注释部分)
代码中注释掉了一个参数网格param_grid和网格搜索(GridSearchCV)的相关代码。这部分的作用是:- 定义了一系列可能的超参数组合
- 网格搜索会自动尝试这些组合,找到性能最佳的参数配置
- 这是一种常用的模型调优方法
-
初始化随机森林模型
python
运行
rf = RandomForestClassifier(bootstrap=False, max_depth=20, max_features='log2', min_samples_leaf=1, min_samples_split=2, n_estimators=50, random_state=487)这里使用了一组特定的超参数初始化了随机森林模型,这些参数可能是通过之前的网格搜索得到的最佳参数。
-
训练模型
python
运行
rf.fit(train_data_x, train_data_y)使用训练数据(特征
train_data_x和标签train_data_y)拟合模型。 -
模型预测
python
运行
train_predicted = rf.predict(train_data_x) # 训练数据集的预测结果 test_predicted = rf.predict(test_data_x) # 测试数据集的预测结果分别对训练集和测试集进行预测,得到预测结果。
-
模型评估
python
运行
print('RF的train:\n', metrics.classification_report(train_data_y, train_predicted)) print('RF的test:\n', metrics.classification_report(test_data_y, test_predicted))使用
classification_report函数生成详细的分类评估报告,包括精确率(precision)、召回率(recall)、F1 分数等指标,并打印出来。 -
提取评估结果
python
运行
rf_test_report = metrics.classification_report(test_data_y, test_predicted, digits=6) b = rf_test_report.split() RF_result['recall_0'] = float(b[6]) # 类别为0的召回率 RF_result['recall_1'] = float(b[11]) # 类别为1的召回率 RF_result['recall_2'] = float(b[16]) # 类别为2的召回率 RF_result['recall_3'] = float(b[21]) # 类别为3的召回率 RF_result['acc'] = float(b[25]) # 准确率 result_data['RF'] = RF_result这段代码从评估报告中提取了特定类别的召回率和总体准确率,存储到
RF_result字典中,最后将结果存入result_data。
三·算法--SVM
# '''#####################SVM算法实现代码###########################'''
from sklearn.svm import SVC
from sklearn.model_selection import GridSearchCV
from sklearn import metrics
# 定义参数网格
param_grid = {
'C': [0.01, 0.1, 1, 2], # 惩罚系数
'kernel': ['linear', 'poly', 'rbf', 'sigmoid'], # 核函数类型
'degree': [2, 3, 4, 5], # 多项式核函数的阶数,仅在'poly'核函数下有效
'gamma': ['scale', 'auto'] + [1], # RBF, poly 和 sigmoid的核函数参数
'coef0': [0.1], # 核函数中的独立项,仅在'poly'和'sigmoid'核函数下有效
}
svc = SVC() # 创建SVC分类器实例
## 创建GridSearchCV对象
grid_search = GridSearchCV(svc, param_grid, cv=5)
## 在训练集上执行网格搜索
grid_search.fit(train_data_x, train_data_y)
SVM_result = {}
svm = SVC(C=1, coef0=0.1, degree=4, gamma=1, kernel='poly', probability=True, random_state=10)
svm.fit(train_data_x, train_data_y)
test_predicted = svm.predict(test_data_x) # 测试数据集的预测结果
print('SVM的test:\n', metrics.classification_report(test_data_y, test_predicted)) # 打印测试数据集的
a = metrics.classification_report(test_data_y, test_predicted, digits=6)
b = a.split()
print(a)
SVM_result['recall_0'] = float(b[6]) # 添加类别为0的召回率
SVM_result['recall_1'] = float(b[11]) # 添加类别为1的召回率
SVM_result['recall_2'] = float(b[16]) # 添加类别为2的召回率
SVM_result['recall_3'] = float(b[21]) # 添加类别为3的召回率
SVM_result['acc'] = float(b[25]) # 添加accuracy的结果
result_data['SVM'] = SVM_result
C是惩罚间距的
这段代码实现了使用支持向量机 (SVM) 进行分类任务,并通过网格搜索寻找最佳参数,最后评估模型性能的完整流程。下面是详细讲解:
1. 导入必要的库
python
运行
from sklearn.svm import SVC # SVM分类器
from sklearn.model_selection import GridSearchCV # 网格搜索工具
from sklearn import metrics # 模型评估指标
2. 定义参数网格
python
运行
param_grid = {
'C': [0.01, 0.1, 1, 2], # 惩罚系数,控制正则化强度,值越大惩罚越重
'kernel': ['linear', 'poly', 'rbf', 'sigmoid'], # 核函数类型
'degree': [2, 3, 4, 5], # 多项式核函数的阶数,仅对'poly'有效
'gamma': ['scale', 'auto'] + [1], # 核函数系数,影响模型复杂度
'coef0': [0.1], # 核函数中的独立项,对'poly'和'sigmoid'有效
}
这里定义了要搜索的参数组合,GridSearchCV 会尝试所有可能的组合来找到最佳参数。
3. 网格搜索寻找最佳参数
python
运行
svc = SVC() # 创建SVC分类器实例
grid_search = GridSearchCV(svc, param_grid, cv=5) # 5折交叉验证
grid_search.fit(train_data_x, train_data_y) # 在训练集上执行网格搜索
这部分代码会自动尝试所有参数组合,通过 5 折交叉验证评估性能,找到最佳参数配置。
4. 使用最佳参数训练模型
python
运行
# 这里使用了搜索得到的最佳参数(示例值)
svm = SVC(C=1, coef0=0.1, degree=4, gamma=1, kernel='poly', probability=True, random_state=10)
svm.fit(train_data_x, train_data_y) # 用训练数据拟合模型
probability=True表示允许模型输出概率预测,random_state=10保证结果可复现。
5. 模型评估
python
运行
test_predicted = svm.predict(test_data_x) # 对测试集进行预测
# 打印详细的分类报告,包括precision、recall、f1-score等指标
print('SVM的test:\n', metrics.classification_report(test_data_y, test_predicted))
6. 提取关键指标
python
运行
a = metrics.classification_report(test_data_y, test_predicted, digits=6) # 保留6位小数
b = a.split() # 将报告按空格分割成列表
# 从分割后的列表中提取所需指标
SVM_result['recall_0'] = float(b[6]) # 类别0的召回率
SVM_result['recall_1'] = float(b[11]) # 类别1的召回率
SVM_result['recall_2'] = float(b[16]) # 类别2的召回率
SVM_result['recall_3'] = float(b[21]) # 类别3的召回率
SVM_result['acc'] = float(b[25]) # 整体准确率
result_data['SVM'] = SVM_result # 将结果存入总结果字典
整体流程总结
- 定义要搜索的参数空间
- 通过网格搜索和交叉验证找到最佳参数
- 使用最佳参数训练 SVM 模型
- 在测试集上评估模型性能
- 提取关键评估指标并存储
四·AdaBoost算法实现代码
'''#####################AdaBoost算法实现代码###########################'''
# 随机森林和XGBoost使用的基学习器是决策树,而AdaBoost可以使用其他各种弱学习器。
from sklearn.ensemble import AdaBoostClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn import metrics
# 此处省略网格搜索参数相关代码(如param_grid定义、GridSearchCV创建等)
AdaBoost_reslut = {}
abf = AdaBoostClassifier(algorithm='SAMME',
base_estimator=DecisionTreeClassifier(max_depth=2),
n_estimators=200,
learning_rate=1.0,
random_state=0) # 创建AdaBoost分类器
abf.fit(train_data_x, train_data_y)
train_predicted = abf.predict(train_data_x) # 训练数据集的预测结果
print('AdaBoost的train:\n', metrics.classification_report(train_data_y, train_predicted)) # 打印训练数据集的
test_predicted = abf.predict(test_data_x) # 测试数据集的预测结果
print('AdaBoost的test:\n', metrics.classification_report(test_data_y, test_predicted)) # 打印测试数据集的
a = metrics.classification_report(test_data_y, test_predicted, digits=6)
b = a.split()
AdaBoost_reslut['recall_0'] = float(b[6]) # 添加类别为0的召回率
AdaBoost_reslut['recall_1'] = float(b[11]) # 添加类别为1的召回率
AdaBoost_reslut['recall_2'] = float(b[16]) # 添加类别为2的召回率
AdaBoost_reslut['recall_3'] = float(b[21]) # 添加类别为3的召回率
AdaBoost_reslut['acc'] = float(b[25]) # 添加accuracy的结果
result_data['AdaBoost'] = AdaBoost_reslut
这段代码实现了 AdaBoost 分类算法的训练、预测和结果评估过程。让我为你详细讲解:
首先,代码导入了必要的库:
AdaBoostClassifier:这是 scikit-learn 库中实现 AdaBoost 算法的分类器DecisionTreeClassifier:决策树分类器,这里作为 AdaBoost 的基学习器metrics:scikit-learn 的评估指标模块,用于模型性能评估
核心部分解析:
- 创建 AdaBoost 分类器:
python
运行
abf = AdaBoostClassifier(algorithm='SAMME',
base_estimator=DecisionTreeClassifier(max_depth=2),
n_estimators=200,
learning_rate=1.0,
random_state=0)
algorithm='SAMME':指定使用 SAMME 算法(多类 AdaBoost 的一种实现)base_estimator:指定基学习器为深度为 2 的决策树n_estimators=200:指定集成 200 个基学习器learning_rate=1.0:学习率参数,控制每个基学习器的权重random_state=0:随机种子,保证结果可复现
- 模型训练与预测:
python
运行
abf.fit(train_data_x, train_data_y) # 用训练数据拟合模型
train_predicted = abf.predict(train_data_x) # 对训练数据进行预测
test_predicted = abf.predict(test_data_x) # 对测试数据进行预测
- 模型评估:
python
运行
# 打印训练集的分类报告,包含精确率、召回率、F1分数等
print('AdaBoost的train:\n', metrics.classification_report(train_data_y, train_predicted))
# 打印测试集的分类报告
print('AdaBoost的test:\n', metrics.classification_report(test_data_y, test_predicted))
- 结果数据整理:
python
运行
# 提取测试集评估结果的详细数据
a = metrics.classification_report(test_data_y, test_predicted, digits=6)
b = a.split()
# 将各类别的召回率和整体准确率存入字典
AdaBoost_reslut['recall_0'] = float(b[6]) # 类别0的召回率
AdaBoost_reslut['recall_1'] = float(b[11]) # 类别1的召回率
AdaBoost_reslut['recall_2'] = float(b[16]) # 类别2的召回率
AdaBoost_reslut['recall_3'] = float(b[21]) # 类别3的召回率
AdaBoost_reslut['acc'] = float(b[25]) # 整体准确率
# 将结果存入总的结果字典中
result_data['AdaBoost'] = AdaBoost_reslut
这段代码的特点是使用决策树作为 AdaBoost 的弱学习器,通过集成多个弱学习器构建一个强学习器,最后对模型在训练集和测试集上的表现进行了评估和结果整理。代码中假设是 4 分类问题(因为提取了 0-3 类的召回率)。
五·GNB朴素贝叶斯算法
'''#####################GNB算法实现代码###########################'''
from sklearn.naive_bayes import GaussianNB
from sklearn import metrics
GNB_result = {}
gnb = GaussianNB() # 创建高斯朴素贝叶斯分类器
gnb.fit(train_data_x, train_data_y)
train_predicted = gnb.predict(train_data_x) # 训练数据集的预测结果
print('GNB的train:\n', metrics.classification_report(train_data_y, train_predicted)) # 打印训练数据集的测试结果
test_predicted = gnb.predict(test_data_x) # 测试数据集的预测结果
print('GNB的test:\n', metrics.classification_report(test_data_y, test_predicted)) # 打印测试数据集的测试结果
a = metrics.classification_report(test_data_y, test_predicted, digits=6)
b = a.split()
GNB_result['recall_0'] = float(b[6]) # 添加类别为0的召回率
GNB_result['recall_1'] = float(b[11]) # 添加类别为1的召回率
GNB_result['recall_2'] = float(b[16]) # 添加类别为2的召回率
GNB_result['recall_3'] = float(b[21]) # 添加类别为3的召回率
GNB_result['acc'] = float(b[25]) # 添加accuracy的结果
result_data['GNB'] = GNB_result
这段代码实现了高斯朴素贝叶斯(Gaussian Naive Bayes, GNB)分类算法的训练、预测和评估过程,下面逐步解释其功能:
-
导入所需库:
GaussianNB:从 scikit-learn 库中导入高斯朴素贝叶斯分类器metrics:从 scikit-learn 库中导入评估指标模块,用于模型性能评估
-
初始化变量:
- 创建空字典
GNB_result用于存储 GNB 模型的评估结果 - 实例化高斯朴素贝叶斯分类器
gnb = GaussianNB()
- 创建空字典
-
模型训练:
- 使用
gnb.fit(train_data_x, train_data_y)对模型进行训练 train_data_x是训练数据集的特征train_data_y是训练数据集的标签(类别)
- 使用
-
训练集预测与评估:
train_predicted = gnb.predict(train_data_x):使用训练好的模型对训练数据进行预测metrics.classification_report():生成详细的分类评估报告,包括精确率、召回率、F1 分数等- 打印训练集的评估报告,用于查看模型在训练数据上的表现
-
测试集预测与评估:
test_predicted = gnb.predict(test_data_x):使用模型对测试数据进行预测- 打印测试集的评估报告,用于评估模型的泛化能力
digits=6参数指定评估报告中数值的小数位数为 6 位
-
提取关键评估指标:
- 将评估报告按空格分割成列表
b - 从列表中提取特定位置的数值作为评估指标:
- 类别 0-3 的召回率(recall)
- 整体准确率(accuracy)
- 将这些指标存储到
GNB_result字典中
- 将评估报告按空格分割成列表
-
保存结果:
- 将
GNB_result字典存入result_data字典的 "GNB" 键下,便于后续与其他模型结果进行比较
- 将
六·Xgboost
import xgboost as xgb
from sklearn import metrics
# 假设 train_data_x、train_data_y、test_data_x、test_data_y 已提前定义好数据
# 若未定义,需补充数据加载、预处理等代码,比如用 pandas 读取并拆分特征和标签
# XGBoost 算法实现代码
XGBoost_result = {}
xgb_model = xgb.XGBClassifier(
learning_rate=0.05, # 学习率
n_estimators=200, # 决策树数量
num_class=5,
max_depth=7, # 树的最大深度
min_child_weight=1, # 叶子节点中最小的样本权重和
gamma=0, # 节点分裂所需的最小损失函数下降值
colsample_bytree=0.8, # 每棵树随机采样的列数的占比
objective='multi:softmax', # 损失函数类型(多分类场景)
seed=0 # 随机数种子
) # 创建 XGBoost 分类器
# 训练模型
xgb_model.fit(train_data_x, train_data_y)
# 训练集预测与评估
train_predicted = xgb_model.predict(train_data_x)
print('XGBoost的train:\n', metrics.classification_report(train_data_y, train_predicted))
# 测试集预测与评估
test_predicted = xgb_model.predict(test_data_x)
print('XGBoost的test:\n', metrics.classification_report(test_data_y, test_predicted))
# 提取详细评估指标到 XGBoost_result
a = metrics.classification_report(test_data_y, test_predicted, digits=6)
b = a.split()
XGBoost_result['recall_0'] = float(b[6]) # 类别为0的召回率
XGBoost_result['recall_1'] = float(b[11]) # 类别为1的召回率
XGBoost_result['recall_2'] = float(b[16]) # 类别为2的召回率
XGBoost_result['recall_3'] = float(b[21]) # 类别为3的召回率
XGBoost_result['acc'] = float(b[25]) # 准确率
# 若有 result_data 字典用于汇总不同模型结果,可按如下方式整合
result_data = {}
result_data['XGBoost'] = XGBoost_result
这段代码实现了随机森林(Random Forest)分类算法,并对模型性能进行了评估和结果记录。下面是详细讲解:
1. 导入必要的库
python
运行
from sklearn.ensemble import RandomForestClassifier
- 从 scikit-learn 库的集成学习模块中导入了
RandomForestClassifier类,用于构建随机森林分类模型
2. 网格搜索参数(注释部分)
这部分代码定义了用于网格搜索的参数范围,但目前处于注释状态:
python
运行
# param_grid = {
# 'n_estimators': [50, 100, 200], # 树的数量
# 'max_depth': [None, 10, 20, 30], # 树的深度
# 'min_samples_split': [2, 5, 10], # 节点分裂所需的最小样本数
# 'min_samples_leaf': [1, 2, 5], # 叶子节点所需的最小样本数
# 'max_features': ['auto', 'sqrt', 'log2'], # 最大特征数
# 'bootstrap': [True, False] # 是否使用自举样本
# }
- 网格搜索(Grid Search)用于自动寻找最佳参数组合
- 如果需要调参,可以取消这些注释并运行相关代码
3. 模型初始化与训练
python
运行
RF_result = {} # 用于存储模型评估结果的字典
# 初始化随机森林分类器,使用指定的参数
rf = RandomForestClassifier(
bootstrap=False, # 不使用自举样本
max_depth=20, # 树的最大深度为20
max_features='log2', # 每个节点考虑的最大特征数为log2(n_features)
min_samples_leaf=1, # 叶子节点的最小样本数为1
min_samples_split=2, # 节点分裂所需的最小样本数为2
n_estimators=50, # 森林中树的数量为50
random_state=487 # 随机数种子,保证结果可复现
)
# 在训练数据上拟合模型
rf.fit(train_data_x, train_data_y)
4. 模型预测
python
运行
train_predicted = rf.predict(train_data_x) # 对训练数据进行预测
test_predicted = rf.predict(test_data_x) # 对测试数据进行预测
- 分别在训练集和测试集上进行预测,用于评估模型的拟合效果和泛化能力
5. 模型评估
python
运行
# 打印训练集的分类报告
print('RF的train:\n', metrics.classification_report(train_data_y, train_predicted))
# 打印测试集的分类报告
print('RF的test:\n', metrics.classification_report(test_data_y, test_predicted))
metrics.classification_report会生成详细的分类评估指标,包括精确率(precision)、召回率(recall)、F1 分数等- 同时打印训练集和测试集的结果,可以对比模型是否过拟合
6. 结果提取与存储
python
运行
# 获取测试集的详细分类报告(保留6位小数)
rf_test_report = metrics.classification_report(test_data_y, test_predicted, digits=6)
b = rf_test_report.split() # 将报告字符串分割成列表,便于提取数值
# 提取各类别的召回率和整体准确率
RF_result['recall_0'] = float(b[6]) # 类别为0的召回率
RF_result['recall_1'] = float(b[11]) # 类别为1的召回率
RF_result['recall_2'] = float(b[16]) # 类别为2的召回率
RF_result['recall_3'] = float(b[21]) # 类别为3的召回率
RF_result['acc'] = float(b[25]) # 整体准确率
# 将随机森林的结果存入总的结果字典中
result_data['RF'] = RF_result
最后保存数据
import json # 数据格式,网络传输。保存提取json类型的数据。
# 使用 'w' 模式打开文件,确保如果文件已存在则会被覆盖,
result = {}
result['mean fill'] = result_data
with open(r'temp_data/平均值填充result.json', 'w', encoding='utf-8') as file:
# 使用 json.dump() 方法将字典转换为 JSON 格式并写入文件,JSON 一般来是字典
json.dump(result, file, ensure_ascii=False, indent=4)
json方便网络传输,任何编程语言都可以读取,json是字符类型的文件,所以用open就可以
更多推荐



所有评论(0)