Bohrium
robot
新建

空间站广场

论文
Notebooks
比赛
课程
Apps
我的主页
我的Notebooks
我的论文库
我的足迹

我的工作空间

任务
节点
文件
数据集
镜像
项目
数据库
公开
分类问题与材料筛选副本
Tutorial
机器学习
Tutorial机器学习
bohr8aed3d
更新于 2024-09-14
推荐镜像 :Basic Image:bohrium-notebook:2023-04-07
推荐机型 :c2_m4_cpu
logistic_regression_data(v1)

分类问题

什么是分类问题?

分类问题是监督学习的一个核心任务,目标是预测给定输入数据点所属的类别或组

在分类问题中,模型被训练来识别不同的类别或标签,基于输入特征将每个数据点分配到这些预定义的类别之一。

分类问题的类型

  1. 二分类问题:最简单的分类类型,只涉及两个类别。模型需要决定一个给定的输入属于这两个类别中的哪一个。典型的例子包括垃圾邮件检测(邮件是垃圾邮件还是非垃圾邮件)和疾病诊断(患者是否患有某种疾病)。

  2. 多类分类问题:当有两个以上的类别时,问题就变成了多类分类。在这种情况下,模型需要从多个选项中选择一个作为预测。例如,手写数字识别(0到9,共10个类别)和图像分类(识别图像中的对象类别)。

  3. 多标签分类问题:在多标签分类问题中,每个实例可以同时属于多个类别。这与多类分类不同,后者每个实例只能归入一个类别。例如,一篇新闻文章可以同时被标记为“政治”、“经济”和“国际”。

机器学习中能解决的分类问题

在机器学习和特别是在科学领域中,分类问题广泛存在,用于将实体、事件或观测值根据其特征划分到预定义的类别或类中。机器学习在解决这类问题时展现了强大的能力,特别是在以下几个方面:

1. 化学和材料科学

  • 化合物分类:根据化合物的结构或性质,预测其属于哪一类化学品,如药物、有机化合物等。
  • 新材料发现:通过材料的物理和化学属性进行分类,帮助预测新材料的性能和潜在应用。

2. 医学和生物学

  • 疾病诊断:利用患者的临床数据、生化指标、影像数据等,来预测疾病的存在,如癌症诊断、心脏病风险评估等。
  • 基因表达分类:分析基因表达数据,以识别不同类型的癌症或预测药物反应。

3. 其他应用

  • 语言和文本:在计算语言学中,对文本进行分类,如情感分析、主题识别等。
  • 图像和声音识别:在计算机视觉和音频处理领域,对图像和声音进行分类,如面部识别、音乐风格分类等。

这些问题展现了机器学习在科学领域内的广泛应用和潜力。通过对数据进行精确的分类,研究人员能够发现新的知识,加速科学发现的进程,并在多个领域内推动创新。


代码
文本

逻辑回归:基于统计方法

代码
文本

1. 逻辑回归概述

逻辑回归是一种广泛应用于分类问题的统计方法,尤其是在二分类问题中。尽管名称中包含“回归”,但逻辑回归实际上是一种分类算法,用于预测一个观察值属于某个类别的概率。

1.1 逻辑回归的基本原理

逻辑回归是一种广泛使用的分类算法,尤其是在二分类问题中。要了解逻辑回归,首先要了解线性回归。

我们最常见的线性回归函数的一般形式是:

写成矩阵形式为:

我们可以通过联系函数,将线性回归方程变换为 ,以实现分类模型,而这个联系函数对于逻辑回归来说,就是 Sigmoid 函数。

Sigmoid 函数:

让我们来绘制一下 Sigmoid 函数:

代码
文本
[37]
import numpy as np
import matplotlib.pyplot as plt

def sigmoid(x):
return 1 / (1 + np.exp(-x))

x = np.linspace(-7.5, 7.5, 1000)
y = sigmoid(x)

plt.figure(figsize=(8, 4)) # 设置图形大小
plt.plot(x, y, color='black') # 使用黑色绘制 sigmoid 函数
plt.title('Sigmoid Function')
plt.xlabel('x')
plt.ylabel('sigmoid(x)')

for spine in plt.gca().spines.values():
spine.set_visible(False)
plt.axvline(x=0, color='gray', alpha=0.5)
plt.axhline(y=0, color='gray', alpha=0.5)

plt.grid(alpha=0.3, color='gray') # 使用灰色网格线
plt.show()
代码
文本

Sigmoid 函数是一个 型的函数,当自变量 趋近正无穷时,因变量 趋近于 1,而当 趋近负无穷时, 趋近于 0,它能够将任何实数映射到 (0, 1) 区间,这样,当接近 0 时样本标签为类别 0,接近 1 时样本标签为类别1,我们就得到了一个二分类模型。

代码
文本

公式推导(选学)

逻辑回归的核心是逻辑函数(Logistic function),也称为Sigmoid函数,其形式为:

其中, 是输入变量的线性组合,可以表达为:

或者更简洁地表示为向量形式:

其中, 是模型参数(包括权重和偏置), 是扩展的特征向量(第一项为 ,对应于偏置 )。

Sigmoid函数的性质

Sigmoid函数将任意实数映射到(0, 1)区间,使其可以解释为概率。具体地,给定一个特征向量 ,模型计算出的 表示 属于正类(标记为)的概率,可以表示为:

相应地,属于负类(标记为 )的概率为:

逻辑回归的目标函数

逻辑回归使用最大似然估计(Maximum Likelihood Estimation, MLE)来估计模型参数。目标是最大化观测数据的似然函数,即最大化数据在当前模型参数下出现的概率。

对于二分类问题,似然函数为:

由于 根据 的值有两种不同的表达形式,可以将似然函数重写为:

为了便于优化,通常对似然函数取对数得到对数似然函数:

最后,通过梯度上升(或等价地,对数似然的负值——即对数损失函数——的梯度下降)来找到使 最大化的 值。

代码
文本

1.2 逻辑回归的输出

根据Sigmoid函数的定义,可知逻辑回归的输出是一个介于0和1之间的概率值,表示给定输入特征下,观察值属于正类(通常编码为1)的概率。通过设置一个阈值(通常是0.5),我们可以将概率值转换为类别标签,以完成分类。如果概率大于或等于阈值,观察值被分类为正类;否则,为负类(通常编码为0)。

1.3 逻辑回归的优点

  • 简单且高效:逻辑回归模型简单易懂,计算效率高,易于实现。
  • 概率输出:提供观察值属于各个类别的概率估计,不仅仅是类别标签。
  • 可解释性:模型参数直观,易于理解,可以解释每个特征对预测结果的影响。
  • 广泛应用:适用于二分类问题,也可以通过技术如“一对多”()扩展到多分类问题。

1.4 逻辑回归的缺点

  • 线性边界:逻辑回归假设数据是线性可分的,对于非线性关系可能无法很好地拟合。
  • 特征空间限制:对于具有复杂特征关系的数据集,逻辑回归可能不如决策树或神经网络等模型表现好。
  • 高度依赖数据表现:需要适当的特征工程和选择合适的特征才能达到良好的性能。

总结来说,逻辑回归是一个强大而灵活的工具,适用于许多不同类型的分类问题,特别是当你需要快速实现一个基准模型或解释模型预测时。


代码
文本

2. 导入数据集

代码
文本

高熵合金()是一类独特的多主元素合金(),可以作为单相固溶体结晶。自 年被提出以来, 引起了广泛的关注,不仅因为其优越的性能,还因为它为合金设计开辟了一个广阔的新领域。到目前为止, 的组成空间中极小的部分已经通过试错方法进行了研究,周期表中有 多种金属元素,有效识别 的相位并找到所有可能的 组成是一个巨大的挑战。

目前,研究人员使用高配位熵混合焓原子尺寸差等参数来识别 ,但这些参数并不稳健。热力学计算方法(如CALPHAD)和第一性原理计算在计算相稳定性方面更有效,但受限于计算成本和数据范围。机器学习(ML)在从现有数据中提取隐含关系方面表现出优势。

在这里,我们选择参考文献 [1] 中的数据集,该数据集收集了 个经实验合成的 样品,包含 个微观结构表征。(我们只考虑最常见的铸态样品,以排除加工条件和热力学处理的影响。排除含有稀土元素或轻元素(除 外)的样品以及相不确定的样品,以降低复杂性。不考虑密堆积六方 ,因为它们通常包含稀土元素。)

所以,我们得到了一个包含 个不同铸态 样品的数据集,其中包含 个组分元素。其中,有 个样品具有单个 相, 个样品具有单个 相。其余的 个样品具有多相、金属间化合物或非晶相,用 标记,表示“不形成单相固溶体”。三元到九元 的百分比以及 相的比例如图 () 所示。大多数样品由五个或六个元素组成,而单相 仅占很小一部分。数据集中有 个元素(),它们的出现次数如图 () 所示。我们发现 个以上的样品中出现,而 仅出现一次。

alt Image from PhysRevMaterials.3.095005, page 3.png

特征构建的热力学参数被用作候选特征,可以通过以下方程计算:

其中, 分别表示第 i 个元素的摩尔分数、原子半径、熔点、价电子浓度和 Pauling 电负性。N 是组成元素的数量,R 是气体常数。 是二元液态合金的混合焓,来源于 Miedema's 理论 [3]。

最稳定的二元化合物的形成焓 可以从参考文献 [4] 中得出,也被认为是候选特征。所有样品的特征都经过归一化处理:

代码
文本
[38]
import numpy as np
import pandas as pd

df = pd.read_csv("/bohr/logisticregdata-xvta/v1/Data_BCC-FCC.csv")
df
Alloy VEC Tm HIM rd ΔH SC χd Ref. Phase
0 HfNbTiZr 4.25 2331.25 -22 0.05 3.59 1.39 0.09 [S1] BCC
1 MoNbTaW 5.50 3157.75 -193 0.02 -9.90 1.39 0.19 [S2] BCC
2 NbTaTiV 4.75 2541.00 -122 0.04 -0.11 1.39 0.03 [S3] BCC
3 Al0.25NbTaTiV 4.65 2446.41 -428 0.04 -10.75 1.53 0.03 [S3] BCC
4 Al0.5NbTaTiV 4.56 2362.33 -428 0.04 -19.08 1.58 0.03 [S3] BCC
... ... ... ... ... ... ... ... ... ... ...
56 Co1.5CrFeMo0.1Ni1.5Ti0.5 8.05 1874.13 -484 0.05 -15.89 1.61 0.07 [S18] FCC
57 CoCrCuFeMnNi 8.50 1727.33 -115 0.03 2.17 1.79 0.08 [S21] FCC
58 CoCrFeMnNbNi 7.50 1959.33 -2505 0.05 -17.73 1.79 0.08 [S21] FCC
59 CoCrFeMnNiV0.25 7.86 1819.38 -286 0.03 -7.91 1.72 0.08 [S31] FCC
60 Al0.5CoCrCuFeNiTi0.2 8.12 1701.70 -677 0.05 -10.99 1.86 0.07 [S32] FCC

61 rows × 10 columns

代码
文本
[39]
df['Phase'].value_counts()
FCC    43
BCC    18
Name: Phase, dtype: int64
代码
文本

数据集包含以下列:

  • Alloy:合金的成分。
  • VECTmHIMrdΔHSCχd:合金的性质,分别代表价电子浓度、熔点、混合焓、原子半径差、熵变、剪切模量和电负性差。
  • Ref:参考文献来源。
  • Phase:合金的相态,包括(体心立方)、(面心立方)和(其他相态)。

接下来,为了进行分类,我们将:

  1. 选择合金性质的列(VEC、Tm、HIM、rd、ΔH、SC、χd)作为特征进行训练。
  2. 使用“Phase”列作为标签。

让我们挑选两个特征,在低维空间中可视化查看数据的分布情况。在这里,我们绘制了 两个向量空间

代码
文本

2.1 特征关联分析

首先,我们需要准备数据,分析一下数据中所有特征的关联度,并将数据中相态(Phase)从字符串类型转换为数值类型以便于可视化。

代码
文本
[40]
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np

# 读取数据集
#df = pd.read_csv('/path/to/Data_BCC-FCC.csv')

# 选择第二列到第八列作为特征数据
features = df.iloc[:, 1:8]

# 计算特征之间的关联度(皮尔逊相关系数)
correlation_matrix = features.corr()

# 可视化特征之间的关联度
plt.figure(figsize=(8, 6))
sns.heatmap(correlation_matrix, annot=True, cmap='coolwarm')
plt.title('Feature Correlation Matrix')
plt.show()
代码
文本

特征关联矩阵Feature Correlation Matrix)中,数值表示特征之间的关联度,具体是通过皮尔逊相关系数Pearson correlation coefficient)来衡量的。皮尔逊相关系数的取值范围是从 ,数值的意义如下:

  • 正数:表示特征之间存在正相关关系。当一个特征的值增加时,另一个特征的值也会增加。数值越接近+1,表明正相关关系越强。

  • :表示特征之间没有线性相关关系。这不意味着它们完全独立,可能存在非线性关系。

  • 负数:表示特征之间存在负相关关系。当一个特征的值增加时,另一个特征的值会减少。数值越接近-1,表明负相关关系越强。

在实际应用中,通过分析特征之间的相关性,可以帮助我们理解数据中的变量是如何相互关联的,从而在构建模型时做出更合理的决策。

代码
文本

2.2 数据可视化

  • 选取特征画图

依据特征关联矩阵选择相关度较高的两个特征用以低维空间展示

代码
文本
[41]
import matplotlib.pyplot as plt

# rd-versus-H Room
df_rd_H = pd.concat([df['rd'], df['ΔH'], df['Phase']], axis=1)
df_rd_H["Phase"] = df_rd_H["Phase"].replace({"FCC": 0, "BCC": 1})
X2 = df_rd_H.iloc[:, :2].values
y2 = df_rd_H.iloc[:, 2].values

# Tm-versus-VEC Room
df_omega_VEC = pd.concat([df['Tm'], df['VEC'], df['Phase']], axis=1)
df_omega_VEC["Phase"] = df_omega_VEC["Phase"].replace({"FCC": 0, "BCC": 1})
X3 = df_omega_VEC.iloc[:, :2].values
y3 = df_omega_VEC.iloc[:, 2].values
代码
文本

接着,使用matplotlibscatter方法在两个子图中分别可视化这些数据。这里我们创建了一个 列的子图布局。

代码
文本
[42]
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 4))

# 可视化 rd - ΔH
ax1.scatter(X2[y2==0, 0], X2[y2==0, 1], c='red', marker='o', s=10, label='FCC', alpha=0.8)
ax1.scatter(X2[y2==1, 0], X2[y2==1, 1], c='blue', marker='s', s=10, label='BCC', alpha=0.8)
ax1.set_title('$r_d$ - $\Delta H$')
ax1.set_xlabel('$r_d$')
ax1.set_ylabel('$\Delta H$')
ax1.legend()

# 可视化 Tm - VEC
ax2.scatter(X3[y3==0, 0], X3[y3==0, 1], c='red', marker='o', s=10, label='FCC', alpha=0.8)
ax2.scatter(X3[y3==1, 0], X3[y3==1, 1], c='blue', marker='s', s=10, label='BCC', alpha=0.8)
ax2.set_title('$T_m$ - $VEC$')
ax2.set_xlabel('$T_m$')
ax2.set_ylabel('$VEC$')
ax2.legend()

plt.show()
代码
文本

在上述代码中,每个scatter调用绘制了一个相态的数据点,其中 相态的点用红色表示, 相态的点用蓝色表示。我们为每个散点图设置了标题、 轴和 轴标签,并添加了图例以区分不同的相态。

空间中, 似乎可以很好地区分 样本。

代码
文本

3. 数据预处理

在数据集中各个特征的数据范围存在较大差距,因此需要使用标准化方法对特征数据进行处理。

为实现在二维平面内可视化,选择上述的 作为两个主要的特征进行模型训练。

代码
文本
[43]
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

# 提取特征和标签
X = pd.concat([df["Tm"], df["VEC"]], axis=1).values
Y = df.iloc[:, -1].replace({"BCC": 0, "FCC": 1})

# 若要使用所有标签,请将下面代码的注释去掉
#X = df.iloc[:, 1:-2].values

# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.2, random_state=42)

# 数据标准化
standard_scaler = StandardScaler()
X_train_standard = standard_scaler.fit_transform(X_train)
X_test_standard = standard_scaler.transform(X_test)
代码
文本
[44]
help(df.replace)
已隐藏输出
代码
文本
  • :首先使用pandas的read_csv函数从CSV文件中加载数据到DataFrame df。
  • :然后,将 这两列作为特征(X),并将最后一列(相态)作为标签(Y)。相态被转换为数值形式,其中表示为 表示为
  • :使用MinMaxScaler对特征进行标准化,使其范围在0到1之间。
代码
文本

4. 二分类问题:逻辑回归模型建立与可视化

代码
文本

逻辑回归有着基于训练数据求解参数 的需求,并且希望训练出来的模型能够尽可能地拟合训练数据,即模型在训练集上的预测准确率越靠近100%越好。

因此,我们使用“损失函数"这个评估指标,来衡量参数 的优劣,即这一组参数能否使模型在训练集上表现优异。

其中,θ表示求解出来的一组参数,m是样本的个数,是样本i上真实的标签,是样本i上,基于参数θ计算出来的逻辑回归返回值,是样本i的取值。我们的目标,就是求解出使 最小的 取值。

如果用一组参数建模后,模型在训练集上表现良好,那我们就说模型表现的规律与训练集数据的规律一致,拟合过程中的损失很小,损失函数的值很小,这一组参数就优秀;相反,如果模型在训练集上表现糟糕,损失函数就会很大,模型就训练不足,效果较差,这一组参数也就比较差。

即是说,我们在求解参数 时,追求损失函数最小,让模型在训练数据上的拟合效果最优,即预测准确率尽量靠近 100%。

由于我们追求损失函数的最小值,让模型在训练集上表现最优,可能会引发另一个问题:如果模型在训练集上表示优秀,却在测试集上表现糟糕,模型就会过拟合。虽然逻辑回归和线性回归是天生欠拟合的模型,但我们还是需要控制过拟合的技术来帮助我们调整模型,对逻辑回归中过拟合的控制,通过正则化来实现。

代码
文本

4.1 使用 两个变量建立逻辑回归模型

代码
文本

4.1.1 模型训练

代码
文本
[45]
from sklearn.linear_model import LogisticRegression

# 创建逻辑回归模型实例
lr = LogisticRegression(penalty="l2", C=10.0)

# 使用特征和标签训练模型
lr.fit(X_train_standard, y_train)

# 模型评分
score = lr.score(X_train_standard, y_train)
print(f"训练数据的准确度是 {score:.2f}")
训练数据的准确度是 0.98
代码
文本
[46]
help(LogisticRegression)
已隐藏输出
代码
文本
[47]
help(lr.score)
已隐藏输出
代码
文本
  • : 正则化类型。在这个例子中,我们使用 L2 正则化。正则化是一种减少模型复杂度以防止过拟合的技术。L2 正则化将模型参数的平方和作为惩罚项添加到损失函数中。L2 正则化不会产生稀疏权重矩阵,但会使权重较小,从而限制模型复杂度。L2 正则化可以防止过拟合,提高模型泛化能力,尤其在数据量较小的情况下更为有效。
  1. : 用于优化问题的算法。在这个例子中,我们使用 liblinear 求解器。liblinear 是一个用于解决大规模线性分类问题的库,适用于较小的数据集。对于较大的数据集,可以考虑使用像 sagalbfgs 这样的求解器。

  2. : 正则化强度的倒数。 是一个正数,其值越小,正则化强度越强。这意味着当 较小时,模型更倾向于选择较小的参数值。在这个例子中,我们将 设置为

代码
文本

模型推断:

  • predict:函数直接返回预测的类别
  • predict_proba:函数返回对应类别的概率。注意对二分类问题,概率会返回两个类别的概率
代码
文本
[48]
## 返回对应类别
y_pred = lr.predict(X_test_standard)
y_pred
array([0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1])
代码
文本
[49]
# 返回对应类别的概率
y_pred_pro = lr.predict_proba(X_test_standard)
print(f'the shape is {y_pred_pro.shape}')
y_pred_pro
the shape is (13, 2)
array([[9.99997001e-01, 2.99856655e-06],
       [5.72866046e-01, 4.27133954e-01],
       [3.49509269e-02, 9.65049073e-01],
       [9.16472249e-02, 9.08352775e-01],
       [7.33913422e-01, 2.66086578e-01],
       [4.73948687e-02, 9.52605131e-01],
       [4.04365510e-03, 9.95956345e-01],
       [4.79678342e-02, 9.52032166e-01],
       [7.12304360e-01, 2.87695640e-01],
       [5.97810593e-03, 9.94021894e-01],
       [8.97763823e-03, 9.91022362e-01],
       [5.62770601e-02, 9.43722940e-01],
       [4.35196415e-01, 5.64803585e-01]])
代码
文本

4.1.2 模型评估

对测试数据进行分类预测,并与原始分类比较。

代码
文本
[50]
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, log_loss, confusion_matrix, classification_report

y_pred = lr.predict(X_test_standard)

acc_score = accuracy_score(y_test, y_pred)

con_matrix = confusion_matrix(y_test, y_pred)
precision_score = precision_score(y_test, y_pred)
recall_score = recall_score(y_test, y_pred)
f1_score = f1_score(y_test, y_pred)

classification_report = classification_report(y_test, y_pred)

print("模型测试结果: ")
print(f'正确率: {acc_score} \n')
print(f'混淆矩阵:\n{con_matrix}')
print(f'精确度: {precision_score}')
print(f'召回率: {recall_score}')
print(f'F1 SCORE: {f1_score}')
print(classification_report)
模型测试结果: 
正确率: 0.9230769230769231 

混淆矩阵:
[[4 1]
 [0 8]]
精确度: 0.8888888888888888
召回率: 1.0
F1 SCORE: 0.9411764705882353
              precision    recall  f1-score   support

           0       1.00      0.80      0.89         5
           1       0.89      1.00      0.94         8

    accuracy                           0.92        13
   macro avg       0.94      0.90      0.92        13
weighted avg       0.93      0.92      0.92        13

代码
文本

这段代码使用了sklearn库的多个函数来评估逻辑回归模型lr的性能。以下是每个指标的含义和这段代码的解析:

  1. 准确率(Accuracy): 表示模型预测正确的样本占总样本的比例。它是最直观的性能评估指标。

  2. 混淆矩阵(Confusion Matrix): 是一个表格,用于描述分类模型的性能,显示实际类别和模型预测类别的组合情况。它主要包括四个部分:

    • 真正例(True Positives, TP): 正确地将正例预测为正例。
    • 假负例(False Negatives, FN): 错误地将正例预测为负例。
    • 假正例(False Positives, FP): 错误地将负例预测为正例。
    • 真负例(True Negatives, TN): 正确地将负例预测为负例。
  3. 精确度(Precision): 是指所有被模型预测为正例的样本中,实际为正例的比例。精确度高表示误报(假正例)的情况较少。

  4. 召回率(Recall): 是指所有实际为正例的样本中,被模型正确预测为正例的比例。召回率高表示漏报(假负例)的情况较少。

  5. F1分数(F1 Score): 是精确度和召回率的调和平均,用于综合反映模型的性能。F1分数越高,说明模型的精确度和召回率之间的平衡越好。

  6. 分类报告(Classification Report): 提供每个类别的精确度、召回率和F1分数,以及宏/微平均值,是一种综合评估分类模型性能的方法。

代码解析:

  • y_pred = lr.predict(X_test_standard): 使用训练好的逻辑回归模型lr对测试集X_test_standard进行预测,得到预测结果y_pred
  • acc_score = accuracy_score(y_test, y_pred): 计算模型的准确率。
  • con_matrix = confusion_matrix(y_test, y_pred): 计算模型的混淆矩阵。
  • precision_score = precision_score(y_test, y_pred): 计算模型的精确度。
  • recall_score = recall_score(y_test, y_pred): 计算模型的召回率。
  • f1_score = f1_score(y_test, y_pred): 计算模型的F1分数。
  • classification_report = classification_report(y_test, y_pred): 生成模型的分类报告,包括每个类别的精确度、召回率和F1分数,以及宏/微平均值。

注意:如果是多分类问题,precision_scorerecall_scoref1_score需要添加参数average='macro'或其他相关参数以适应多分类的评估。

代码
文本
[51]
from sklearn.metrics import roc_curve, auc
import matplotlib.pyplot as plt

fpr, tpr, thresholds = roc_curve(y_test, y_pred)
roc_auc = auc(fpr, tpr)

plt.figure()
plt.plot(fpr, tpr, color='darkorange', lw=2, label='ROC curve (area = %0.2f)' % roc_auc)
plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Receiver operating characteristic example')
plt.legend(loc="lower right")
plt.show()
代码
文本
[52]
fpr
array([0. , 0.2, 1. ])
代码
文本

这段代码演示了如何计算和绘制接收者操作特征曲线(ROC Curve)以及计算曲线下面积(AUC)来评估分类模型的性能。以下是详细的解析和每个概念的介绍:

  1. ROC Curve(接收者操作特征曲线):ROC曲线是一个图形化的评估分类模型性能的工具,它通过比较模型在不同决策阈值下的真正例率(True Positive Rate, TPR)和假正例率(False Positive Rate, FPR)来绘制。其中:

    • TPR(又称灵敏度或召回率)定义为TP / (TP + FN),即在所有实际正例中,被正确预测为正例的比例。
    • FPR定义为FP / (FP + TN),即在所有实际负例中,被错误预测为正例的比例。
  2. AUC(Area Under Curve):AUC值是ROC曲线下的面积,是用来衡量分类模型优劣的一个指标。AUC值的范围在0到1之间,一个完美的分类器的AUC为1,而一个随机分类器的AUC为0.5。AUC越接近1,模型的性能越好。

代码解析:

  • fpr, tpr, thresholds = roc_curve(y_test, y_pred): 使用roc_curve函数计算测试集y_test的真正例率和假正例率以及不同的决策阈值。y_pred是模型对测试集的预测得分或概率。
  • roc_auc = auc(fpr, tpr): 计算ROC曲线下的面积(AUC)。
  • 接着,代码使用matplotlib库绘制ROC曲线,其中横坐标是假正例率(FPR),纵坐标是真正例率(TPR)。曲线标签显示了AUC的值。
  • plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--')绘制了一条对角线,表示一个随机分类器的性能。理想情况下,模型的ROC曲线应该远离这条线并靠近左上角。

通过ROC曲线和AUC值,我们可以评估模型对正负类别的区分能力,尤其在实际应用中类别不平衡的情况下,ROC和AUC是非常有用的性能指标。

代码
文本

4.1.3 模型参数解析

代码
文本
[53]
theta0 = lr.intercept_[0]
theta1 = lr.coef_[0][0]
theta2 = lr.coef_[0][1]
print(f"z(x)={theta0:.2f}+{theta1:.2f} x1+{theta2:.2f} x2")
z(x)=1.74+1.23 x1+5.81 x2
代码
文本
  • :解析逻辑回归模型的参数,包括截距 theta0 和两个特征的系数 theta1theta2
  • :输出逻辑回归模型的方程形式。
代码
文本

4.1.4 概率预测与损失函数计算

损失函数Loss Function)是用于衡量模型预测值实际值之间差异的指标。在机器学习中,损失函数是优化算法的目标函数,用于在训练过程中指导模型的学习。对于分类问题,常用的损失函数之一是对数损失(Log Loss),也称为逻辑损失或交叉熵损失。

对数损失计算模型输出的预测概率与实际标签之间的差异,具体计算公式如下:

其中, 是样本数量, 是样本 的实际标签, 是模型预测样本(i)为正类的概率。

损失函数的值越小,表示模型的预测值与实际值越接近,即模型的性能越好。对数损失的值范围是从0到正无穷,其中0表示模型的预测完全准确。

  • 损失函数的大小:损失函数的具体值取决于模型的预测性能。值越接近0,表示预测的准确度越高。值越大,表示模型预测的误差越大。

  • 衡量结果的好坏:通常,对数损失的值需要与其他模型或基线模型进行比较,以确定其相对性能。此外,可以结合其他评价指标(如准确率、召回率、F1分数)来全面评估模型的性能。

代码
文本
[54]
from sklearn.metrics import log_loss

# 计算预测概率
y_pred_proba = lr.predict_proba(X_test_standard)

# 计算损失函数
loss = log_loss(y_test, y_pred_proba)
print(f"The loss function of the model is: {loss:.4f}")
The loss function of the model is: 0.1803
代码
文本
[55]
lr.predict_proba(X_test_standard)
array([[9.99997001e-01, 2.99856655e-06],
       [5.72866046e-01, 4.27133954e-01],
       [3.49509269e-02, 9.65049073e-01],
       [9.16472249e-02, 9.08352775e-01],
       [7.33913422e-01, 2.66086578e-01],
       [4.73948687e-02, 9.52605131e-01],
       [4.04365510e-03, 9.95956345e-01],
       [4.79678342e-02, 9.52032166e-01],
       [7.12304360e-01, 2.87695640e-01],
       [5.97810593e-03, 9.94021894e-01],
       [8.97763823e-03, 9.91022362e-01],
       [5.62770601e-02, 9.43722940e-01],
       [4.35196415e-01, 5.64803585e-01]])
代码
文本
  • :使用predict_proba方法预测每个样本属于各个类别的概率。
  • :使用log_loss计算模型的对数损失,这是评估分类器性能的一种方式。

损失函数是 ,表明模型的预测结果与原始数据的差距较小。

代码
文本

4.2 损失函数对决策边界的影响

  • 调整模型的损失函数:正则化是一种用于防止过拟合的技术,通过在损失函数中添加一个正则化项来惩罚模型的复杂度。
  • 在逻辑回归中,参数C控制正则化的强度。较小的C值表示更强的正则化,可以减小模型复杂度,从而降低损失函数的值。
代码
文本

4.2.1 导入必要的库与数据准备

首先,需要导入用于数据处理和绘图的库,以及机器学习中使用的模型和评估函数。

X_train_standardX_test_standard 是经过standardScaler标准化的特征矩阵,Y 是分类目标。为了可视化,我们对特征空间中的训练集 X_train 的每一点使用逻辑回归模型预测其类别,从而绘制决策边界。

代码
文本
[56]
from matplotlib.lines import Line2D
import matplotlib.pyplot as plt
import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, log_loss
代码
文本

4.2.2 绘制结果并添加图例

  • 选择固定的正则化超参数进行模型训练
代码
文本
[57]
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler

# 选择正则化参数C
C = 1

# 初始化逻辑回归模型
model = LogisticRegression(penalty="l2", C=C, solver='lbfgs', max_iter=1000)

# 训练模型
model.fit(X_train_standard, y_train)

# 获取决策边界
slope = -model.coef_[0, 0] / model.coef_[0, 1]
intercept = -model.intercept_ / model.coef_[0, 1]

# 绘制数据点
plt.scatter(X_train_standard[:, 0], X_train_standard[:, 1], c=y_train, cmap='coolwarm', marker='o', label='Training Data')
plt.scatter(X_test_standard[:, 0], X_test_standard[:, 1], c=y_test, cmap='coolwarm', marker='x', alpha=0.5, label='Test Data')

# 绘制决策边界
x_vals = np.array(plt.gca().get_xlim())
y_vals = intercept + (slope * x_vals)
plt.plot(x_vals, y_vals, 'k--', label='Decision Boundary')

# 显示网格
plt.grid(True)

plt.xlabel('$T_m$(standardScaled)')
plt.ylabel('$VEC$(standardScaled)')
plt.title('Decision Boundary by Logistic Regression')
plt.legend()
plt.show()

代码
文本
  • 探究在不同正则化参数下模型的性能
代码
文本
[72]
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler

# 选择一系列正则化参数C
Cs = [0.5, 1, 10, 100, 1000]
colors = ['c', 'm', 'y', 'g', 'blue'] # 分配不同的颜色以区分不同的C值

plt.figure(figsize=(8, 5))

# 绘制原始数据点
plt.scatter(X_train_standard[:, 0], X_train_standard[:, 1], c=y_train, cmap='coolwarm', marker='o', label='Training Data')
plt.scatter(X_test_standard[:, 0], X_test_standard[:, 1], c=y_test, cmap='coolwarm', marker='x', alpha=0.5, label='Test Data')

# 初始化一个空列表来存储C值及其相应模型的预测准确度
detail = []

for C, color in zip(Cs, colors):
# 初始化并训练逻辑回归模型
model = LogisticRegression(penalty="l2", C=C, solver='lbfgs', max_iter=1000)
model.fit(X_train_standard, y_train)
# 计算决策边界
slope = -model.coef_[0, 0] / model.coef_[0, 1]
intercept = -model.intercept_ / model.coef_[0, 1]
# 提取边界(直线)参数,方便输出方程
theta0 = model.intercept_[0]
theta1 = model.coef_[0][0]
theta2 = model.coef_[0][1]
# 绘制决策边界
x_vals = np.linspace(plt.gca().get_xlim()[0], plt.gca().get_xlim()[1], 100)
y_vals = intercept + slope * x_vals
plt.plot(x_vals, y_vals, color=color, linestyle='--', label=f'C={C}')

# 使用模型预测测试集
y_pred = model.predict(X_test_standard)
# 存储C值、相应的损失值以及对应的边界方程到列表中
detail.append({"C": C
,"Accuracy": accuracy_score(y_test, y_pred)
,"decision_border": f"z(x)={theta0:.2f}+{theta1:.2f}x1+{theta2:.2f}x2"
})

# 显示网格
plt.grid(True)

plt.xlabel('$T_m$(standardScaled)')
plt.ylabel('$VEC$(standardScaled)')
plt.title('Decision Boundary by Logistic Regression with Different C')
plt.legend(loc='upper right')
plt.show()

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
File /opt/conda/lib/python3.8/site-packages/matplotlib/axes/_axes.py:4439, in Axes._parse_scatter_color_args(c, edgecolors, kwargs, xsize, get_next_color_func)
   4438 try:  # Is 'c' acceptable as PathCollection facecolors?
-> 4439     colors = mcolors.to_rgba_array(c)
   4440 except (TypeError, ValueError) as err:

File /opt/conda/lib/python3.8/site-packages/matplotlib/colors.py:487, in to_rgba_array(c, alpha)
    486 else:
--> 487     rgba = np.array([to_rgba(cc) for cc in c])
    489 if alpha is not None:

File /opt/conda/lib/python3.8/site-packages/matplotlib/colors.py:487, in <listcomp>(.0)
    486 else:
--> 487     rgba = np.array([to_rgba(cc) for cc in c])
    489 if alpha is not None:

File /opt/conda/lib/python3.8/site-packages/matplotlib/colors.py:299, in to_rgba(c, alpha)
    298 if rgba is None:  # Suppress exception chaining of cache lookup failure.
--> 299     rgba = _to_rgba_no_colorcycle(c, alpha)
    300     try:

File /opt/conda/lib/python3.8/site-packages/matplotlib/colors.py:381, in _to_rgba_no_colorcycle(c, alpha)
    380 if not np.iterable(c):
--> 381     raise ValueError(f"Invalid RGBA argument: {orig_c!r}")
    382 if len(c) not in [3, 4]:

ValueError: Invalid RGBA argument: 2.0

The above exception was the direct cause of the following exception:

ValueError                                Traceback (most recent call last)
Cell In[72], line 13
     10 plt.figure(figsize=(8, 5))
     12 # 绘制原始数据点
---> 13 plt.scatter(X_train_standard[:, 0], X_train_standard[:, 1], c=y_train, cmap='coolwarm', marker='o', label='Training Data')
     14 plt.scatter(X_test_standard[:, 0], X_test_standard[:, 1], c=y_test, cmap='coolwarm', marker='x', alpha=0.5, label='Test Data')
     16 # 初始化一个空列表来存储C值及其相应模型的预测准确度

File /opt/conda/lib/python3.8/site-packages/matplotlib/pyplot.py:2862, in scatter(x, y, s, c, marker, cmap, norm, vmin, vmax, alpha, linewidths, edgecolors, plotnonfinite, data, **kwargs)
   2857 @_copy_docstring_and_deprecators(Axes.scatter)
   2858 def scatter(
   2859         x, y, s=None, c=None, marker=None, cmap=None, norm=None,
   2860         vmin=None, vmax=None, alpha=None, linewidths=None, *,
   2861         edgecolors=None, plotnonfinite=False, data=None, **kwargs):
-> 2862     __ret = gca().scatter(
   2863         x, y, s=s, c=c, marker=marker, cmap=cmap, norm=norm,
   2864         vmin=vmin, vmax=vmax, alpha=alpha, linewidths=linewidths,
   2865         edgecolors=edgecolors, plotnonfinite=plotnonfinite,
   2866         **({"data": data} if data is not None else {}), **kwargs)
   2867     sci(__ret)
   2868     return __ret

File /opt/conda/lib/python3.8/site-packages/matplotlib/__init__.py:1442, in _preprocess_data.<locals>.inner(ax, data, *args, **kwargs)
   1439 @functools.wraps(func)
   1440 def inner(ax, *args, data=None, **kwargs):
   1441     if data is None:
-> 1442         return func(ax, *map(sanitize_sequence, args), **kwargs)
   1444     bound = new_sig.bind(ax, *args, **kwargs)
   1445     auto_label = (bound.arguments.get(label_namer)
   1446                   or bound.kwargs.get(label_namer))

File /opt/conda/lib/python3.8/site-packages/matplotlib/axes/_axes.py:4602, in Axes.scatter(self, x, y, s, c, marker, cmap, norm, vmin, vmax, alpha, linewidths, edgecolors, plotnonfinite, **kwargs)
   4599 if edgecolors is None:
   4600     orig_edgecolor = kwargs.get('edgecolor', None)
   4601 c, colors, edgecolors = \
-> 4602     self._parse_scatter_color_args(
   4603         c, edgecolors, kwargs, x.size,
   4604         get_next_color_func=self._get_patches_for_fill.get_next_color)
   4606 if plotnonfinite and colors is None:
   4607     c = np.ma.masked_invalid(c)

File /opt/conda/lib/python3.8/site-packages/matplotlib/axes/_axes.py:4445, in Axes._parse_scatter_color_args(c, edgecolors, kwargs, xsize, get_next_color_func)
   4443 else:
   4444     if not valid_shape:
-> 4445         raise invalid_shape_exception(c.size, xsize) from err
   4446     # Both the mapping *and* the RGBA conversion failed: pretty
   4447     # severe failure => one may appreciate a verbose feedback.
   4448     raise ValueError(
   4449         f"'c' argument must be a color, a sequence of colors, "
   4450         f"or a sequence of numbers, not {c!r}") from err

ValueError: 'c' argument has 257 elements, which is inconsistent with 'x' and 'y' with size 800.
代码
文本
[59]
# 打印C值及其相应损失值
detail_df = pd.DataFrame(detail)

print("Losses for different C values:")
print(detail_df)
Losses for different C values:
        C  Accuracy           decision_border
0     0.5  0.692308   z(x)=1.24+0.05x1+1.96x2
1     1.0  0.692308   z(x)=1.33+0.25x1+2.66x2
2    10.0  0.923077   z(x)=1.74+1.23x1+5.81x2
3   100.0  1.000000  z(x)=2.56+2.93x1+11.34x2
4  1000.0  1.000000  z(x)=5.16+3.42x1+28.93x2
代码
文本

可以看到,随着正则化参数C的增大,逻辑回归模型的决策边界明显不同,性能得到提示。

代码
文本

4.3 远离边界的数据点对决策边界的影响(选学)

代码
文本
[60]
from matplotlib.lines import Line2D
from sklearn.metrics import accuracy_score

# 删除远端的点,例如,只保留 6<VEC<8 的那些点
df_2 = df[(df["VEC"] > 6) & (df["VEC"] < 9)]

# 提取特征和标签
X = pd.concat([df_2["Tm"], df_2["VEC"]], axis=1).values
Y = df_2.iloc[:, -1].replace({"BCC": 0, "FCC": 1})

# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.2, random_state=42)

# 数据标准化
standard_scaler = StandardScaler()
X_train_standard = standard_scaler.fit_transform(X_train)
X_test_standard = standard_scaler.transform(X_test)

# 绘制散点图与决策边界
colors = ["red", "blue"]
figure = plt.figure(dpi=300)
plt.figure(figsize=(8, 5))
# plt.scatter(Xs[:, 0], Xs[:, 1], c=[colors[y] for y in Y], s=15)
plt.scatter(X_train_standard[:, 0], X_train_standard[:, 1], c=[colors[y] for y in y_train], s=15)
plt.scatter(X_test_standard[:, 0], X_test_standard[:, 1], c=[colors[y] for y in y_test], s=15, marker='x')

ax = plt.gca() # 实例化我们的图

# 在平面上制作一个足够细的网格,来代表我们“平面上的所有点”。
xlim = ax.get_xlim() # 获取横坐标的最大值和最小值
ylim = ax.get_ylim() # # 获取纵坐标的最大值和最小值

# 在最大值和最小值之间形成 30 个规律的数据
axisx = np.linspace (xlim[0], xlim[1], 60)
axisy = np.linspace (ylim[0], ylim[1], 60)

# 使用 meshgrid 函数将两个一维向量转化为特征矩阵
axisy,axisx = np.meshgrid(axisy ,axisx)

# 使用 notebook 查看 axisx, axisy 和 axisx.shape, axisy.shape
xy = np.vstack([axisx.ravel(), axisy.ravel()]).T # 其中 ravel() 是降维函数,vstack 能够将多个结构一致的一维数组按行堆叠起夹

Cs = [5e-1, 1, 10, 100, 1000] # 使用不同的 C 参数
line_colors = ['c', 'm', 'y', 'g', 'blue']

# Initialize an empty list to store C values and their corresponding losses
losses = []

# 使用 sklearn 的逻辑回归模型绘制决策边界
for i, C in enumerate(Cs):
lr = LogisticRegression(penalty="l2",C=C).fit(X_train_standard, y_train)
theta0 = lr.intercept_[0]
theta1 = lr.coef_[0][0]
theta2 = lr.coef_[0][1]
Z = lr.decision_function(xy).reshape(axisx.shape)
v = ax.contour(axisx, axisy, Z, levels=[0], colors=line_colors[i], alpha=0.5)

# Calculate prediction probabilities
y_pred_proba = lr.predict_proba(X_train_standard)

# Calculate loss function
loss = log_loss(y_train, y_pred_proba)
# 使用模型预测
y_pred = lr.predict(X_train_standard)
# Save the C value and its corresponding loss in the list
losses.append({"C": C
,"Loss": loss
,"Accuracy": accuracy_score(y_train, y_pred)
,"decision_border": f"z(x)={theta0:.2f}+{theta1:.2f}x1+{theta2:.2f}x2"
})

# 创建图例
legend_elements = [Line2D([0], [0], linestyle='-', color=line_colors[i], label=f'C = {C}') for i, C in enumerate(Cs)]
plt.legend(handles=legend_elements)

ax.set_xlabel('$T_m$(StandardScaled)')
ax.set_ylabel('$VEC$(StandardScaled)')
ax.set_xlim(xlim)
ax.set_ylim(ylim)

plt.show()
<Figure size 1920x1440 with 0 Axes>
代码
文本
[61]
# Print the DataFrame containing C values and their corresponding losses
losses_df = pd.DataFrame(losses)

print("Losses for different C values:")
print(losses_df)
Losses for different C values:
        C      Loss  Accuracy           decision_border
0     0.5  0.152619   0.95122   z(x)=1.80+0.48x1+1.75x2
1     1.0  0.110952   0.95122   z(x)=2.02+0.57x1+2.32x2
2    10.0  0.030774   1.00000   z(x)=3.25+1.02x1+5.09x2
3   100.0  0.006547   1.00000   z(x)=5.45+1.70x1+9.17x2
4  1000.0  0.001107   1.00000  z(x)=8.45+2.63x1+14.43x2
代码
文本

可以看到,在不考虑一些远离边界地方的点后,我们的分类超平面与之前有很大的不同。

但存在一个FCC的测试集数据未能被正确划分的问题。

代码
文本

4.4 小结

逻辑回归是一个返回对数几率的广泛使用的分类算法,在线性数据上表现优异的分类器。

逻辑回归的数学目的是求解能够让模型最优化的参数 的值,并基于参数 和特征矩阵计算出逻辑回归的结果

  1. 逻辑回归对线性关系的拟合效果较好

  2. 逻辑回归计算快

  3. 逻辑回归返回的分类结果不是固定的 。而是以小数形式呈现的类概率数字。获取方式为

from sklearn.linear_model import LogisticRegression

LogisticRegression().score()

然而,在某些情况下,逻辑回归可能表现不佳:

  1. 损失值(Loss Value)较小的线: 在逻辑回归中,我们的目标是找到一个能够将数据点尽可能正确分类的决策边界。为了实现这一目标,我们通常使用损失函数(例如交叉熵损失)来衡量模型的表现。损失值越小,模型的表现越好。

然而,在某些情况下,可能存在多条损失值较小的线,这些线在数据集上的表现相近。这可能导致模型在选择最优决策边界时出现困难。例如,在数据点重叠或呈非线性分布的情况下,逻辑回归可能无法找到一个明确的最优决策边界。

  1. 远离边界的点影响分类超平面: 逻辑回归试图找到一个能够最大化分类正确率的决策边界。在这个过程中,每个数据点都会对决策边界产生一定的影响。然而,在某些情况下,这种影响可能导致模型过拟合或欠拟合。

例如,假设在一个二分类问题中,大多数数据点都紧密地聚集在两个不同的区域,但存在一些异常值远离这两个区域。在这种情况下,逻辑回归可能会将这些远离边界的点考虑在内,从而导致决策边界向这些点偏移。这可能导致模型在测试集上的性能下降,因为决策边界可能不再是最佳的分类超平面。

综上所述,逻辑回归在某些情况下可能存在一些问题。为了解决这些问题,我们可以尝试使用其他分类算法(如支持向量机、决策树等)或使用正则化技术来限制模型的复杂度。此外,对数据进行预处理(例如去除异常值、降维等)也有助于改善模型的性能。

代码
文本

5. 多分类问题(Softmax回归)

Softmax回归(也称为多项逻辑回归)是逻辑回归模型在多类分类问题上的推广。逻辑回归通常用于二分类问题,而Softmax回归则允许模型处理多个类别。

5.1 原理与概念

在softmax回归中,对于每个输入样本,模型会计算每个类别的得分(也称为logits),然后通过softmax函数将这些得分转换为概率。softmax函数的关键在于,它可以确保所有类别的预测概率之和为1,使得这些概率可以直接解释为给定输入属于每个类别的概率。

具体来说,假设我们有一个分类问题,目标是从K个可能的类别中选择一个。对于每个输入样本,softmax模型首先计算每个类别的得分,通常是通过线性函数计算得到,其中分别是类别的权重和偏置项。然后,softmax函数被应用于这些得分,以计算每个类别的概率:

这里,表示在给定输入的条件下,目标类别的概率。分子是类别的得分的指数,分母是所有类别得分指数的和,这确保了所有类别概率之和为1。


代码
文本

5.2 合金相态分类

在原始的数据集中包括合金成分、性质和相态,我们将使用这些信息来训练一个能够识别三种相态(FCC、BCC、NSP)的模型。下面是一个简化的流程示例,使用scikit-learn库进行操作。

要使用softmax对合金的相态进行分类,并进行分类的可视化,我们需要先完成以下步骤:

  1. 数据探索和预处理:加载数据,探索数据的基本结构,检查是否需要进行数据清洗或预处理。
  2. 特征选择和数据划分:选择用于分类的特征(合金的成分和性质),并将数据划分为训练集和测试集。
  3. 模型构建:构建一个使用softmax函数的分类模型。
  4. 训练模型:使用训练集数据来训练模型。
  5. 模型评估:使用测试集数据评估模型的性能。
  6. 可视化:对分类结果进行可视化,以便于理解模型的分类效果。

5.2.1 数据加载和预处理

加载数据

由于说多分类问题,因此我们需要重新加载数据,导入包含FCC、BCC、NSP三种相态的数据集

代码
文本
[62]
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler, LabelEncoder
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score

# 重新加载数据
data_path = '/bohr/logisticregdata-xvta/v1/Data.csv'
df = pd.read_csv(data_path)
df
Alloy VEC Tm HIM rd ΔH SC χd Ref. Phase
0 HfNbTiZr 4.25 2331.25 -22 0.05 3.59 1.39 0.09 [S1] BCC
1 MoNbTaW 5.50 3157.75 -193 0.02 -9.90 1.39 0.19 [S2] BCC
2 NbTaTiV 4.75 2541.00 -122 0.04 -0.11 1.39 0.03 [S3] BCC
3 Al0.25NbTaTiV 4.65 2446.41 -428 0.04 -10.75 1.53 0.03 [S3] BCC
4 Al0.5NbTaTiV 4.56 2362.33 -428 0.04 -19.08 1.58 0.03 [S3] BCC
... ... ... ... ... ... ... ... ... ... ...
317 CoCrCuFeMnNiTiV 7.50 1811.00 -435 0.05 -12.11 2.08 0.09 [S10] NSP
318 Al0.125CoCrCuFeMnNiTiV 7.43 1797.49 -677 0.06 -14.12 2.13 0.09 [S10] NSP
319 Al0.125CoCrCuFeNiTiMnV 7.43 1797.49 -677 0.06 -14.12 2.13 0.09 [S10] NSP
320 Al0.67CoCrCuFeMnNiTiV 7.15 1743.15 -677 0.06 -21.53 2.19 0.08 [S10] NSP
321 Al0.67CoCrCuFeNiTiMnV 7.15 1743.15 -677 0.06 -21.53 2.19 0.08 [S10] NSP

322 rows × 10 columns

代码
文本
[63]
df['Phase'].value_counts()
NSP    261
FCC     43
BCC     18
Name: Phase, dtype: int64
代码
文本

再次载入的数据中不仅包好了 还包含了

代码
文本

划分数据与预处理

分离特征与标签,并划分数据集和测试集

代码
文本
[64]
import numpy as np
# 分离特征和标签
X = df.iloc[:, 1:8].values # 假设第二列到第八列是合金性质
y = df.iloc[:, -1].values # 假设最后一列是合金的相态

# 执行条件赋值
y[y == 'BCC'] = 0
y[y == 'FCC'] = 1
y[y == 'NSP'] = 2

# 将字符串类型的数字转换为整数类型
y = y.astype('int')

# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 数据标准化
scaler = StandardScaler()
X_train_standard = scaler.fit_transform(X_train)
X_test_standard = scaler.transform(X_test)
代码
文本

5.2.2 建立softmax回归模型

scikit-learn中,LogisticRegression类支持多分类设置,通过设置multi_class='multinomial'来使用softmax回归。

代码
文本
[65]
# 建立softmax回归模型
model = LogisticRegression(multi_class='multinomial', max_iter=200)

# 训练模型
model.fit(X_train_standard, y_train)

# 预测测试集
y_pred = model.predict(X_test_standard)

# 评估模型性能
accuracy = accuracy_score(y_test, y_pred)
print(f'Accuracy: {accuracy:.4f}')
Accuracy: 0.8462
代码
文本

模型的准确率为84.62%,这表明在测试集上的表现相对较好。

代码
文本

5.2.3 评估模型性能

混淆矩阵

接下来,我们将使用混淆矩阵来可视化模型的分类效果,进一步分析模型对于不同相态的分类能力。

代码
文本
[66]
from sklearn.metrics import confusion_matrix

# 计算混淆矩阵
conf_matrix = confusion_matrix(y_test, y_pred)
print("Confusion Matrix:")
print(conf_matrix)

# 标注正确分类和错误分类
print("\n正确分类:")
for i in range(3): # 假设有三个类别
print(f"类别{i}正确分类数量: {conf_matrix[i, i]}")

print("\n错误分类:")
for i in range(3):
for j in range(3):
if i != j:
print(f"实际为类别{i}但预测为类别{j}的数量: {conf_matrix[i, j]}")
Confusion Matrix:
[[ 2  0  3]
 [ 0  2  6]
 [ 0  1 51]]

正确分类:
类别0正确分类数量: 2
类别1正确分类数量: 2
类别2正确分类数量: 51

错误分类:
实际为类别0但预测为类别1的数量: 0
实际为类别0但预测为类别2的数量: 3
实际为类别1但预测为类别0的数量: 0
实际为类别1但预测为类别2的数量: 6
实际为类别2但预测为类别0的数量: 0
实际为类别2但预测为类别1的数量: 1
代码
文本
  • : ; : ; :

  • 对于三分类问题,混淆矩阵是一个3x3的矩阵。在这个矩阵中,对角线上的元素依然表示正确分类的数量,即每个类别被正确预测为该类别的次数。

  • 矩阵中的其他元素表示错误分类的情况,具体来说,矩阵的第i行第j列的元素表示实际为类别i但被错误预测为类别j的次数。

混淆矩阵展示了模型在预测不同合金相态上的表现。横轴代表模型预测的相态,纵轴代表真实的相态。每个单元格的数值表示真实相态和预测相态相匹配的样本数。这种可视化帮助我们理解模型在区分不同相态(BCC、FCC、NSP)时的性能如何。

代码
文本

特征重要性图

显示不同特征对模型预测相态的贡献程度,帮助理解哪些特征对模型的决策过程最为关键。

由于我们使用的是逻辑回归模型,我们可以直接绘制特征重要性图。对于精确度-召回率曲线和ROC曲线,通常需要使用支持概率预测的分类器,逻辑回归模型可以提供这种概率预测,但需要对每个类别分别绘制这些曲线。

首先,我们将展示特征重要性图,以了解哪些合金的性质在预测合金相态时起到了关键作用。

代码
文本
[67]
# Display feature importance for the logistic regression model
feature_names = df.columns[1:-2]

feature_importance = pd.DataFrame(model.coef_[0], index=feature_names, columns=['Importance']).sort_values(by='Importance', ascending=False)

# Plot the feature importances
plt.figure(figsize=(8, 5))
feature_importance['Importance'].plot(kind='bar')
plt.title('Feature Importance')
plt.xlabel('Features')
plt.ylabel('Importance')
plt.show()
代码
文本

特征重要性图展示了不同合金性质对模型预测相态的影响程度。每个条形代表一个特征(合金的性质),其长度表示该特征对模型预测结果的影响力大小。这有助于我们理解哪些特征对合金相态的预测更为重要。

代码
文本

6. 参考

代码
文本

7. 随堂作业

在这次作业中,我们将探索如何使用逻辑回归模型预测材料是否具有某种特定的物理性质,例如是否为导电材料。在材料科学中,能够根据材料的化学组成预测其导电性是非常有用的,尤其是在搜索新型导电材料时。

场景

假设我们正在研究一系列化合物,并希望基于化合物的电负性差异()和原子半径差异()来预测这些化合物是否为导电材料。

数据

为了模拟这一问题,我们给大家提供了一个简单的数据集 (condacting_material_data.csv):

  • 导电材料通常具有较小的电负性差异和较大的原子半径差异。
  • 非导电材料则相反。

作业要求

  1. 读取数据集,并查看数据集内容
  2. 将特征和标签数据进行划分;再划分训练集和测试集
  3. 对训练数据与测试数据进行标准化
  4. 使用逻辑回归进行训练(要求设置对多个正则化参数C训练)
  5. 对模型的精度进行评估并输出准确度
  6. 绘制训练数据点(用o表示)与测试数据点(用x表示)
  7. 绘制决策边界线
代码
文本
[68]
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
import matplotlib.pyplot as plt

# 读取数据集
df = pd.read_csv('/bohr/logisticregdata-xvta/v1/condacting_material_data.csv')
df
Delta_X Delta_r Conductivity
0 1.470229 0.355596 0
1 0.720086 0.389247 0
2 1.038306 0.257769 0
3 1.732491 0.310471 0
4 1.527157 0.322805 0
... ... ... ...
995 1.727079 0.709775 1
996 1.390881 0.840152 1
997 1.551806 0.715843 1
998 0.868814 0.585810 1
999 1.303037 0.568903 1

1000 rows × 3 columns

代码
文本
[90]
# 分割数据集
X = df.iloc[:,:2].values
Y = df.iloc[:,-1]
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2, random_state=42)
0      0
1      0
2      0
3      0
4      0
      ..
995    1
996    1
997    1
998    1
999    1
Name: Conductivity, Length: 1000, dtype: int64
代码
文本
[91]
# 标准化数据
standard_scaler = StandardScaler()
X_train_standard = standard_scaler.fit_transform(X_train)
X_test_standard = standard_scaler.transform(X_test)
代码
文本
[98]
# 选择多个正则化参数C
Cs = [0.01, 0.1, 1, 10, 100]
colors = ['c', 'm', 'y', 'g', 'blue'] # 分配不同的颜色以区分不同的C值

plt.figure(figsize=(8, 5))

# 绘制原始数据点
plt.scatter(X_train_standard[:, 0], X_train_standard[:, 1], c=Y_train, cmap='coolwarm', marker='o',alpha=0.5, label='Training Data')
plt.scatter(X_test_standard[:, 0], X_test_standard[:, 1], c=Y_test, cmap='coolwarm', marker='x', alpha=0.5, label='Test Data')

# 初始化一个空列表来存储C值及其相应模型的预测准确度
detail = []

for C, color in zip(Cs, colors):
# 初始化并训练逻辑回归模型
model = LogisticRegression(penalty="l2", C=C, solver='lbfgs', max_iter=1000)
model.fit(X_train_standard, Y_train)
# 计算决策边界
slope = -model.coef_[0, 0] / model.coef_[0, 1]
intercept = -model.intercept_ / model.coef_[0, 1]
# 提取边界(直线)参数,方便输出方程
theta0 = model.intercept_[0]
theta1 = model.coef_[0][0]
theta2 = model.coef_[0][1]
# 绘制决策边界
x_vals = np.linspace(plt.gca().get_xlim()[0], plt.gca().get_xlim()[1], 100)
y_vals = intercept + (slope * x_vals)
plt.plot(x_vals, y_vals, color=color, linestyle='--', label=f'C={C}')

# 使用模型预测测试集
y_pred = model.predict(X_test_standard)
# 存储C值、相应的损失值以及对应的边界方程到列表中
detail.append({"C": C
,"Accuracy": accuracy_score(Y_test, y_pred)
,"decision_border": f"z(x)={theta0:.2f}+{theta1:.2f}x1+{theta2:.2f}x2"
})

# 显示网格
plt.grid(True)

plt.xlabel('Delta_X (standardScaled)')
plt.ylabel('Delta_r (standardScaled)')
plt.title('Decision Boundary by Logistic Regression with Different C')
plt.legend()
plt.show()
代码
文本
[93]
# 打印C值及其相应损失值
detail_df = pd.DataFrame(detail)

print("Losses for different C values:")
print(detail_df)
Losses for different C values:
        C  Accuracy            decision_border
0    0.01     0.980   z(x)=-0.03+0.67x1+1.19x2
1    0.10     0.985   z(x)=-0.07+1.17x1+2.88x2
2    1.00     0.990   z(x)=-0.18+1.67x1+5.55x2
3   10.00     0.990   z(x)=-0.35+2.29x1+9.72x2
4  100.00     0.980  z(x)=-0.50+2.96x1+14.26x2
代码
文本
Tutorial
机器学习
Tutorial机器学习
点个赞吧
推荐阅读
公开
分类问题与材料筛选副本
Tutorial机器学习
Tutorial机器学习
Anthea
发布于 2024-03-24
公开
分类问题与材料筛选Copy
Tutorial机器学习
Tutorial机器学习
Cai JF
发布于 2024-03-25