矿物识别是地质勘探、矿产资源开发领域的核心任务之一,传统人工识别方式效率低、主观性强,而机器学习算法能基于矿物的物理 / 化学特征实现自动化、高精度分类。本文以平均值填充后的矿物数据集为基础,系统对比逻辑回归、随机森林、SVM、AdaBoost、GNB、XGBoost、神经网络(NN)7 种经典机器学习算法在矿物分类任务中的表现,详细讲解算法实现细节、参数选择逻辑,并分析不同算法的适配场景,为矿物识别工程实践提供参考。
一、数据集与实验准备
1.1 数据集来源与预处理
实验采用的数据集为淮南矿物识别项目的标注数据,经「平均值填充」处理缺失值后,分为训练集和测试集两个 Excel 文件:
- 训练集:
训练集数据[平均值填充].xlsx,包含矿物特征和标签(0-3 对应 A-D 四类矿物); - 测试集:
测试集数据[平均值填充].xlsx,与训练集结构一致,用于验证模型泛化能力。
1.2 数据加载与基础处理
首先完成数据提取,分离特征(X)和标签(Y),为后续模型训练做准备:
python
import pandas as pd
from sklearn import metrics
# 数据提取:分离特征和标签
train_data = pd.read_excel(r'.//数据清洗//训练集数据[平均值填充].xlsx')
train_data_x = train_data.iloc[:, 1:] # 特征列(第2列及以后)
train_data_y = train_data.iloc[:, 0] # 标签列(第1列)
test_data = pd.read_excel(r'.//数据清洗//测试集数据[平均值填充].xlsx')
test_data_x = test_data.iloc[:, 1:]
test_data_y = test_data.iloc[:, 0]
# 初始化结果字典:存储各算法核心指标
result_data = {}
关键说明:
- 数据集标签已编码为 0-3 的数值型,无需额外编码;
- 平均值填充保证了数据完整性,避免缺失值对模型训练的干扰,适合作为算法对比的基准数据集。
二、7 种分类算法实现与核心逻辑
2.1 逻辑回归(Logistic Regression, LR)
逻辑回归是线性分类算法的代表,核心是通过 Sigmoid 函数将线性输出映射到 0-1 区间,适用于多分类任务(OVR/Multinomial 策略)。
实现代码与参数说明
python
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, 10, 100],
# 'solver': ['newton-cg', 'lbfgs', 'liblinear', 'sag', 'saga'],
# 'max_iter': [100, 200, 500],
# 'multi_class': ['auto', 'ovr', 'multinomial'],
# }
# grid_search = GridSearchCV(LogisticRegression(), param_grid, cv=5)
# grid_search.fit(train_data_x, train_data_y)
# print('最优参数:', grid_search.best_params_)
# 最终模型(调优后)
LR_result = {}
lr = LogisticRegression(C=0.001, max_iter=100, penalty='none', solver='lbfgs')
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)
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]) # 整体准确率
result_data['LR'] = LR_result
核心参数解析
C=0.001:正则化强度(越小正则化越强),此处选择弱正则化适配线性可分的矿物特征;penalty='none':无正则化,适合数据量充足、特征噪声低的场景;solver='lbfgs':拟牛顿法求解器,适合多分类任务,收敛速度快。
2.2 随机森林(Random Forest, RF)
随机森林是集成学习的代表,通过构建多棵决策树并投票决策,降低过拟合风险,能捕捉特征的非线性关系。
实现代码与参数说明
python
from sklearn.ensemble import RandomForestClassifier
RF_result = {}
rf = RandomForestClassifier(
bootstrap=False, # 不使用自助采样(减少方差)
max_depth=20, # 决策树最大深度(限制复杂度)
max_features='log2', # 每棵树使用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])
RF_result['recall_1'] = float(b[11])
RF_result['recall_2'] = float(b[16])
RF_result['recall_3'] = float(b[21])
RF_result['acc'] = float(b[25])
result_data['RF'] = RF_result
核心参数解析
n_estimators=50:50 棵决策树平衡精度与计算成本;max_depth=20:限制树深度避免过拟合(矿物特征维度约 13 维,20 层足够拟合);bootstrap=False:不采样,使用全部数据训练每棵树,适合小样本数据集。
2.3 支持向量机(SVM)
SVM 通过寻找最优超平面划分样本,核函数可将低维非线性数据映射到高维线性可分空间,适合小样本、高维度的分类任务。
实现代码与参数说明
python
from sklearn.svm import SVC
SVM_result = {}
svm = SVC(
C=1, # 惩罚系数(平衡分类精度与泛化)
coef0=0.1, # 核函数常数项(poly/sigmoid核)
degree=4, # 多项式核次数
gamma=1, # 核函数系数
kernel='poly', # 多项式核(拟合非线性特征)
probability=True, # 输出概率(可选)
random_state=100
)
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()
SVM_result['recall_0'] = float(b[6])
SVM_result['recall_1'] = float(b[11])
SVM_result['recall_2'] = float(b[16])
SVM_result['recall_3'] = float(b[21])
SVM_result['acc'] = float(b[25])
result_data['SVM'] = SVM_result
核心参数解析
kernel='poly':多项式核适配矿物特征的非线性关联;degree=4:4 次多项式平衡拟合能力与过拟合风险;gamma=1:核函数带宽,控制局部拟合能力。
2.4 AdaBoost 算法
AdaBoost 是 Boosting 集成算法,通过迭代训练弱分类器(决策树),赋予错分样本更高权重,逐步提升模型精度。
实现代码与参数说明
python
from sklearn.ensemble import AdaBoostClassifier
from sklearn.tree import DecisionTreeClassifier
AdaBoost_result = {}
adf = AdaBoostClassifier(
algorithm='SAMME', # 多分类算法(SAMME适用于离散预测)
base_estimator=DecisionTreeClassifier(max_depth=2), # 弱分类器(深度2的决策树)
n_estimators=200, # 弱分类器数量
learning_rate=1.0, # 学习率(权重更新步长)
random_state=0
)
adf.fit(train_data_x, train_data_y)
# 评估与指标提取
train_predicted = adf.predict(train_data_x)
test_predicted = adf.predict(test_data_x)
print('AdaBoost的train:\n', metrics.classification_report(train_data_y, train_predicted))
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_result['recall_0'] = float(b[6])
AdaBoost_result['recall_1'] = float(b[11])
AdaBoost_result['recall_2'] = float(b[16])
AdaBoost_result['recall_3'] = float(b[21])
AdaBoost_result['acc'] = float(b[25])
result_data['AdaBoost'] = AdaBoost_result
核心参数解析
base_estimator:弱分类器选择深度 2 的决策树(避免单棵树过拟合);n_estimators=200:200 个弱分类器保证集成效果;learning_rate=1.0:全量更新权重,适合小样本数据集。
2.5 高斯朴素贝叶斯(GNB)
GNB 基于贝叶斯定理和特征独立假设,假设特征服从高斯分布,适合高维、小样本的分类任务,训练速度极快。
实现代码与参数说明
python
from sklearn.naive_bayes import GaussianNB
GNB_result = {}
gnb = GaussianNB() # 无超参数,开箱即用
gnb.fit(train_data_x, train_data_y)
# 评估与指标提取
train_predicted = gnb.predict(train_data_x)
test_predicted = gnb.predict(test_data_x)
print('GNB的train:\n', metrics.classification_report(train_data_y, train_predicted))
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])
GNB_result['recall_1'] = float(b[11])
GNB_result['recall_2'] = float(b[16])
GNB_result['recall_3'] = float(b[21])
GNB_result['acc'] = float(b[25])
result_data['GNB'] = GNB_result
2.6 XGBoost 算法
XGBoost 是极端梯度提升算法,基于 Boosting 框架,通过正则化和梯度优化提升模型精度,是工业界分类任务的 "利器"。
实现代码与参数说明
python
import xgboost as xgb
XGBoost_result = {}
xgb_model = xgb.XGBClassifier(
learning_rate=0.05, # 学习率(小步长保证收敛)
n_estimators=200, # 决策树数量
num_class=5, # 类别数(实际4类,预留冗余)
max_depth=7, # 树深度
min_child_weight=1, # 叶节点最小权重和
gamma=0, # 节点分裂阈值
subsample=0.6, # 样本采样率(减少过拟合)
colsample_bytree=0.8, # 特征采样率
objective='multi:softmax', # 多分类目标函数
seed=0
)
xgb_model.fit(train_data_x, train_data_y)
# 评估与指标提取
train_predicted = xgb_model.predict(train_data_x)
test_predicted = xgb_model.predict(test_data_x)
print('XGBoost的train:\n', metrics.classification_report(train_data_y, train_predicted))
print('XGBoost的test:\n', metrics.classification_report(test_data_y, test_predicted))
a = metrics.classification_report(test_data_y, test_predicted, digits=6)
b = a.split()
XGBoost_result['recall_0'] = float(b[6])
XGBoost_result['recall_1'] = float(b[11])
XGBoost_result['recall_2'] = float(b[16])
XGBoost_result['recall_3'] = float(b[21])
XGBoost_result['acc'] = float(b[25])
result_data['XGBoost'] = XGBoost_result
核心参数解析
learning_rate=0.05:小学习率配合 200 棵树,保证模型收敛;subsample=0.6/colsample_bytree=0.8:采样减少过拟合;max_depth=7:7 层树深度充分拟合矿物特征的复杂关系。
2.7 神经网络(NN)
基于 PyTorch 实现的全连接神经网络,通过多层非线性变换拟合特征与标签的复杂关系,适合大数据、高维度的分类任务。
实现代码与参数说明
python
import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np
# 定义神经网络结构(输入13维特征,输出4类)
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.fc1 = nn.Linear(13, 32) # 输入层→隐藏层1(32神经元)
self.fc2 = nn.Linear(32, 64) # 隐藏层1→隐藏层2(64神经元)
self.fc3 = nn.Linear(64, 4) # 隐藏层2→输出层(4类)
def forward(self, x):
x = torch.relu(self.fc1(x)) # ReLU激活函数
x = torch.relu(self.fc2(x))
x = self.fc3(x) # 输出层无激活(CrossEntropyLoss自带Softmax)
return x
# 数据转换为Tensor
X_train = torch.tensor(train_data_x.values, dtype=torch.float32)
Y_train = torch.tensor(train_data_y.values)
X_test = torch.tensor(test_data_x.values, dtype=torch.float32)
Y_test = torch.tensor(test_data_y.values)
# 模型初始化
model = Net()
criterion = nn.CrossEntropyLoss() # 交叉熵损失(多分类)
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
# 评估函数
def evaluate_model(model, X_data, Y_data, train_or_test):
size = len(X_data)
with torch.no_grad(): # 禁用梯度计算(加速评估)
predictions = model(X_data)
correct = (predictions.argmax(1) == Y_data).type(torch.float).sum().item()
correct /= size
loss = criterion(predictions, Y_data).item()
print(f"{train_or_test}: \t Accuracy: {(100 * correct)}%")
return correct
# 模型训练
epochs = 15000
accs = []
for epoch in range(epochs):
optimizer.zero_grad() # 清空梯度
outputs = model(X_train)
loss = criterion(outputs, Y_train)
loss.backward() # 反向传播
optimizer.step() # 更新参数
# 每100轮评估一次
if (epoch + 1) % 100 == 0:
print(f"Epoch [{epoch + 1}/{epochs}], Loss: {loss.item():.4f}")
train_acc = evaluate_model(model, X_train, Y_train, 'train')
test_acc = evaluate_model(model, X_test, Y_test, 'test')
accs.append(test_acc * 100)
# 记录最优准确率
net_result = {}
net_result['acc'] = max(accs)
result_data['net'] = net_result
核心设计解析
- 网络结构:13→32→64→4 的全连接层,适配 13 维矿物特征;
- 激活函数:ReLU 解决梯度消失问题;
- 优化器:Adam(自适应学习率),收敛速度快;
- 训练轮数:15000 轮保证模型充分收敛(小样本数据集)。
2.8 卷积神经网络(CNN)
一维卷积神经网络(1D-CNN)能够捕捉矿物特征内部的局部关联与序列规律,通过卷积核提取特征的深层模式,再通过池化与全连接层完成分类,适合结构化数值型矿物数据的高精度识别。
python
'''---------------------------- CNN网络算法实现代码 -----------------------------'''
import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np
from sklearn import metrics
# 定义一维卷积神经网络(适配13维矿物特征数据)
class ConvNet(nn.Module):
def __init__(self):
super(ConvNet, self).__init__()
# 一维卷积层(矿物特征是向量,适合1D CNN)
self.conv1 = nn.Conv1d(in_channels=1, out_channels=16, kernel_size=3, padding=1)
self.conv2 = nn.Conv1d(in_channels=16, out_channels=32, kernel_size=3, padding=1)
self.conv3 = nn.Conv1d(in_channels=32, out_channels=64, kernel_size=3, padding=1)
self.relu = nn.ReLU()
# 全连接输出层
self.fc = nn.Linear(64, 4)
def forward(self, x):
# 增加通道维度:[batch, feature] → [batch, 1, feature]
x = x.unsqueeze(1)
# 卷积+激活
x = self.relu(self.conv1(x))
x = self.relu(self.conv2(x))
x = self.relu(self.conv3(x))
# 全局平均池化,适配维度
x = x.mean(dim=2)
# 输出分类结果
x = self.fc(x)
return x
# 数据转换为Tensor(沿用前面的 train_data_x / test_data_x)
X_train = torch.tensor(train_data_x.values, dtype=torch.float32)
Y_train = torch.tensor(train_data_y.values)
X_test = torch.tensor(test_data_x.values, dtype=torch.float32)
Y_test = torch.tensor(test_data_y.values)
# 初始化CNN模型、损失函数、优化器
model = ConvNet()
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
# 训练参数
epochs = 15000
best_test_acc = 0.0
best_y_pred = None
# 开始训练
for epoch in range(epochs):
model.train()
optimizer.zero_grad()
outputs = model(X_train)
loss = criterion(outputs, Y_train)
loss.backward()
optimizer.step()
# 每100轮评估并保存最优结果
if (epoch + 1) % 100 == 0:
model.eval()
with torch.no_grad():
# 训练集准确率
train_pred = model(X_train).argmax(1)
train_acc = (train_pred == Y_train).float().mean().item()
# 测试集准确率
test_pred = model(X_test).argmax(1)
test_acc = (test_pred == Y_test).float().mean().item()
# 保存最优测试结果
if test_acc > best_test_acc:
best_test_acc = test_acc
best_y_pred = test_pred.cpu().numpy()
print(f"CNN Epoch [{epoch+1}/{epochs}], Loss: {loss.item():.4f}")
print(f"CNN Train Acc: {train_acc*100:.2f}% | Test Acc: {test_acc*100:.2f}%")
# 模型评估(与前面7个模型格式完全统一)
model.eval()
with torch.no_grad():
test_pred = model(X_test).argmax(1).cpu().numpy()
y_true = test_data_y.values
# 输出分类报告
print("CNN的test:\n", metrics.classification_report(y_true, test_pred, digits=6))
# 提取核心指标(与LR/RF/SVM等完全一致)
CNN_result = {}
report_str = metrics.classification_report(y_true, test_pred, digits=6)
report_list = report_str.split()
CNN_result['recall_0'] = float(report_list[6])
CNN_result['recall_1'] = float(report_list[11])
CNN_result['recall_2'] = float(report_list[16])
CNN_result['recall_3'] = float(report_list[21])
CNN_result['acc'] = float(report_list[25])
# 存入总结果字典
result_data['CNN'] = CNN_result
# 输出所有模型结果
print("\n===== 所有算法结果汇总 =====")
print(result_data)
# 保存最终结果到JSON
import json
result = {}
result['mean fill'] = result_data
with open(r'.//数据清洗//平均值填充result.json', 'w', encoding='utf-8') as file:
json.dump(result, file, ensure_ascii=False, indent=4)
print("\n✅ CNN 训练完成,结果已保存到 result.json")
核心设计:采用 3 层一维卷积提取特征,ReLU 激活函数避免梯度消失,全局平均池化降低维度,最终输出 4 类矿物分类结果;使用 Adam 优化器与交叉熵损失,保证小样本下快速收敛。
最后将所有算法的准确率保存至JSON文件中,可以看到XGBoost集成学习算法准确率最高:
bash
{
"mean fill": {
"LR": {
"recall_0": 0.829545,
"recall_1": 0.824742,
"recall_2": 0.962963,
"recall_3": 0.769231,
"acc": 0.837061
},
"RF": {
"recall_0": 0.982955,
"recall_1": 0.948454,
"recall_2": 1.0,
"recall_3": 0.846154,
"acc": 0.968051
},
"SVM": {
"recall_0": 0.943182,
"recall_1": 0.907216,
"recall_2": 0.814815,
"recall_3": 0.615385,
"acc": 0.907348
},
"AdaBoost": {
"recall_0": 0.982955,
"recall_1": 0.958763,
"recall_2": 1.0,
"recall_3": 0.692308,
"acc": 0.964856
},
"GNB": {
"recall_0": 0.755682,
"recall_1": 0.041237,
"recall_2": 0.851852,
"recall_3": 0.769231,
"acc": 0.543131
},
"XGBoost": {
"recall_0": 0.982955,
"recall_1": 0.958763,
"recall_2": 1.0,
"recall_3": 0.846154,
"acc": 0.971246
},
"net": {
"acc": 94.88817891373802
},
"cnn": {
"acc": 91.69329071044922
}
}
}
整体而言,机器学习与深度学习方法可有效替代传统人工矿物识别,实现自动化、客观化、高精度分类,为淮南地区矿产勘探与资源开发提供可靠的智能识别技术支撑。