目录
一、人工智能简史
三次浪潮
DL,ML,AI三者之间的关系
二、模型评价指标
混淆矩阵
Overall Accuracy
编辑
Average accuracy
Kappa系数
Recall
Precision
F1
PR曲线
置信度
IOU
AP
mAP
三、常用包Numpy、pandas、matplotlib
Numpy
pandas
matplotlib
四、Jupyter notebook/Lab 简述
安装
学习链接:深入浅出PyTorch — 深入浅出PyTorch (datawhalechina.github.io)
一、人工智能简史
三次浪潮
①1956-1966 人工智能元年 达特茅斯会议
②20世纪80年代 统计学思想引入 提出BP神经网络
③1993年以后 2006年深度学习 2016年AIphaGO围棋
DL,ML,AI三者之间的关系
深度学习(DL)、机器学习(ML)和人工智能(AI)之间的关系可以用层级结构来理解:
-
人工智能(AI):AI是一个广泛的领域,旨在开发能够模拟人类智能的计算机系统。它包括许多子领域,如机器学习、计算机视觉、自然语言处理等。AI的目标是让计算机能够执行通常需要人类智能的任务,例如理解语言、识别图像、做决策等。
-
机器学习(ML):ML是AI的一个子领域,专注于开发算法和统计模型,使计算机能够从数据中学习和做出预测或决策,而不需要明确的编程指令。换句话说,机器学习通过数据驱动的方法来提高AI系统的性能。
-
深度学习(DL):DL是机器学习的一个子领域,主要使用人工神经网络,特别是多层神经网络(深度神经网络),来处理复杂的数据表示和模式识别任务。深度学习在图像识别、语音识别、自然语言处理等方面表现出了极高的效能,是近年来推动AI快速发展的核心技术之一。
总结来说,深度学习是机器学习的一个子集,而机器学习又是人工智能的一个子集。
二、模型评价指标
混淆矩阵
混淆矩阵是评估分类模型性能的重要工具,特别是在二分类和多分类问题中。它以矩阵的形式展示了模型的预测结果与实际标签之间的对比。
混淆矩阵的结构
对于二分类问题,混淆矩阵通常是一个2x2的矩阵,包含以下四个部分:
- True Positive (TP): 真正例。模型正确预测为正类的样本数。
- True Negative (TN): 真负例。模型正确预测为负类的样本数。
- False Positive (FP): 假正例。模型错误地将负类预测为正类的样本数(也称为“类型I错误”)。
- False Negative (FN): 假负例。模型错误地将正类预测为负类的样本数(也称为“类型II错误”)。
实际正类 (Positive) 实际负类 (Negative)
预测正类 (Positive) TP FP
预测负类 (Negative) FN TN
Overall Accuracy
Overall Accuracy(总体准确率)是衡量分类模型性能的一项指标,表示模型正确分类的样本数量占总样本数量的比例。它是混淆矩阵中所有正确分类结果(包括所有类别的正确预测)的总和除以总样本数的结果。
对于二分类或多分类问题,Overall Accuracy 的计算公式是:Overall Accuracy=所有类别的正确预测数/总样本数
如果使用混淆矩阵的表示法,对于二分类问题:Overall Accuracy=(TP+TN)/(TP+TN+FP+FN)
def compute_oa(matrix):
"""
计算总体准确率,OA=(TP+TN)/(TP+TN+FP+FN)
:param matrix:
:return:
"""
return np.trace(matrix) / np.sum(matrix)
Overall Accuracy 是评估模型性能的一个直观指标,但在类别不平衡的数据集上,它可能会掩盖模型在少数类别上的差距。因此,在分析模型性能时,还应考虑其他指标如精确率、召回率和F1分数等。
Average accuracy
Average Accuracy(平均准确率)通常用于多分类问题中,表示每个类别的分类准确率的平均值。这种方法对每个类别的表现给予相同的权重,适合在类别不平衡的数据集上评估模型性能,因为它能够更好地反映模型在所有类别上的表现。
对于 nnn 个类别,首先计算每个类别的分类准确率,然后取这些准确率的平均值。具体公式为:
def compute_aa(matrix):
"""
计算每一类的准确率,AA=(TP/(TP+FN)+TN/(FP+TN))/2
:param matrix:
:return:
"""
return np.mean(np.diag(matrix) / np.sum(matrix, axis=1))
与 Overall Accuracy 的对比
- Overall Accuracy 计算的是所有样本中预测正确的比例,因此在类别不平衡的情况下,少数类别的影响可能会被多数类别掩盖。
- Average Accuracy 则通过计算每个类别的准确率,并取其平均值,使得每个类别对最终结果都有相同的影响,能够更公平地评估模型在不同类别上的表现。
Kappa系数
Kappa系数(Cohen's Kappa)是一种统计指标,用于衡量分类模型的预测结果与实际类别之间的一致性。与简单的准确率不同,Kappa系数考虑了分类中的偶然因素(即,随机猜测所带来的准确性),因此可以提供比准确率更可靠的一致性评估。
Cohen's Kappa 系数的计算公式为:
具体步骤
Kappa 系数的解读
- κ=1 表示完全一致,即模型的预测结果与实际类别完全一致。
- κ=0\kappa = 0κ=0 表示模型的预测结果与随机猜测的结果没有区别。
- κ<0\kappa < 0κ<0 表示一致性低于随机水平,模型的表现比随机猜测还要差。
Kappa 系数的具体值通常按以下标准解读:
- 0.81-1.00:几乎完美的一致性
- 0.61-0.80:显著一致性
- 0.41-0.60:中等一致性
- 0.21-0.40:公平一致性
- 0.01-0.20:轻微一致性
- 0.00 或更低:无一致性
import numpy as np
def compute_oa(matrix):
"""
计算总体准确率 (Overall Accuracy)
:param matrix: 混淆矩阵
:return: 总体准确率
"""
return np.trace(matrix) / np.sum(matrix)
def compute_kappa(matrix):
"""
计算Kappa系数
:param matrix: 混淆矩阵
:return: Kappa系数
"""
# 计算总体准确率 (Overall Accuracy)
oa = compute_oa(matrix)
# 计算期望准确率 (Expected Accuracy)
pe = 0
for i in range(len(matrix)):
pe += np.sum(matrix[i]) * np.sum(matrix[:, i])
pe = pe / np.sum(matrix) ** 2
# 计算Kappa系数
kappa = (oa - pe) / (1 - pe)
return kappa
-
计算总体准确率 (Overall Accuracy, OA):
np.trace(matrix)
:计算混淆矩阵的对角线元素之和,即正确分类的总数。np.sum(matrix)
:计算混淆矩阵的所有元素之和,即总样本数。oa = np.trace(matrix) / np.sum(matrix)
:计算总体准确率。
-
计算期望准确率 (Expected Accuracy, PE):
np.sum(matrix[i]) * np.sum(matrix[:, i])
:对于每个类别,计算该类别的行和列的乘积(即分别为实际和预测中的总数)。pe = pe / np.sum(matrix) ** 2
:将上述乘积的累加结果除以总样本数的平方,得到期望准确率。
-
计算 Kappa 系数:
kappa = (oa - pe) / (1 - pe)
:使用总体准确率和期望准确率计算Kappa系数。Kappa系数的范围在[-1, 1]之间,1表示完全一致,0表示与随机一致性相同,负值表示比随机一致性还差。
Recall
Recall(召回率)是分类模型性能评估的重要指标之一,尤其在关注模型能否正确识别正类样本时非常有用。它表示在所有实际为正类的样本中,模型正确预测为正类的比例。
对于二分类问题,Recall的计算公式是:Recall=TP/TP+FN
- TP (True Positive): 真正例,模型正确预测为正类的样本数。
- FN (False Negative): 假负例,模型错误地将正类预测为负类的样本数。
召回率的意义
- 高召回率意味着模型能够识别大部分的正类样本,但可能会增加假阳性(误将负类预测为正类)的数量。
- 召回率通常与精确率(Precision)一起使用。二者之间存在权衡:提高召回率可能会降低精确率,反之亦然。
多分类问题中的 Recall
在多分类问题中,召回率通常是针对每个类别分别计算的,然后可以选择计算每个类别的平均召回率(如微平均、宏平均等)。
- 宏平均(Macro-Averaging): 计算每个类别的召回率,然后取平均值。
- 微平均(Micro-Averaging): 将所有类别的 TP 和 FN 总和,然后计算召回率。
召回率在实际中的应用
- 在医疗诊断中,高召回率意味着较少的漏诊,特别适用于一些不容错过的疾病检测。
- 在信息检索中,高召回率意味着能检索到更多的相关信息。
Recall 是评价模型在实际应用中捕获正类样本能力的重要指标,特别是在对假阴性结果敏感的场景中具有重要意义。
Precision
Precision也称精准率,代表的是在全部预测为正的结果中,被预测正确的正样本所占的比例,用于衡量模型在正类预测中的准确性。
用数学公式表示为:Precision=True Positives (TP)/True Positives (TP)+False Positives (FP)
-
其中:
- True Positives (TP) 是模型正确预测为正类的样本数。
- False Positives (FP) 是模型错误预测为正类的样本数。
精确度高意味着模型在预测正类时较少出现错误的预测(即假阳性)。在处理不平衡数据集时,精确度尤其重要,因为它可以帮助我们评估模型在正类样本上的预测质量。
import torch
def calculate_precision(preds, labels):
"""
计算精确度(Precision)。
参数:
preds (torch.Tensor): 模型的预测结果,0 或 1。
labels (torch.Tensor): 真实标签,0 或 1。
返回:
float: 精确度。
"""
# 计算 True Positives 和 False Positives
true_positives = torch.sum((preds == 1) & (labels == 1)).item()
false_positives = torch.sum((preds == 1) & (labels == 0)).item()
# 计算精确度
precision = true_positives / (true_positives + false_positives) if (true_positives + false_positives) > 0 else 0.0
return precision
# 示例
preds = torch.tensor([1, 0, 1, 1, 0])
labels = torch.tensor([1, 0, 0, 1, 1])
precision = calculate_precision(preds, labels)
print(f"Precision: {precision:.2f}")
F1
F1 分数 是精确度(Precision)和召回率(Recall)的调和平均值,用于综合评估模型的性能。F1 分数在分类任务中尤为重要,特别是在处理不平衡数据集时,它可以提供对模型性能的更全面的评估。
F1 分数的定义:
其中:
- 精确度(Precision):真正正类样本数与所有被预测为正类样本数的比例。
- 召回率(Recall):真正正类样本数与所有真实正类样本数的比例。
import torch
def calculate_f1(preds, labels):
"""
计算 F1 分数。
参数:
preds (torch.Tensor): 模型的预测结果,0 或 1。
labels (torch.Tensor): 真实标签,0 或 1。
返回:
float: F1 分数。
"""
# 计算 True Positives, False Positives 和 False Negatives
true_positives = torch.sum((preds == 1) & (labels == 1)).item()
false_positives = torch.sum((preds == 1) & (labels == 0)).item()
false_negatives = torch.sum((preds == 0) & (labels == 1)).item()
# 计算精确度(Precision)和召回率(Recall)
precision = true_positives / (true_positives + false_positives) if (true_positives + false_positives) > 0 else 0.0
recall = true_positives / (true_positives + false_negatives) if (true_positives + false_negatives) > 0 else 0.0
# 计算 F1 分数
f1_score = 2 * (precision * recall) / (precision + recall) if (precision + recall) > 0 else 0.0
return f1_score
# 示例
preds = torch.tensor([1, 0, 1, 1, 0])
labels = torch.tensor([1, 0, 0, 1, 1])
f1 = calculate_f1(preds, labels)
print(f"F1 Score: {f1:.2f}")
F1 分数的扩展形式,通常称为 Fβ 分数,其中 β 用于控制精确度(Precision)和召回率(Recall)的权重。Fβ 分数的定义式如下:
- 当 β > 1:Fβ 分数更侧重于召回率(Recall)。
- 当 β < 1:Fβ 分数更侧重于精确度(Precision)。
- 当 β = 1:Fβ 分数与 F1 分数相同,平衡了精确度和召回率。
计算全局性能时,通常有两种方法:macro 和 micro。
-
Macro 方法:
- 对每个类别分别计算精确度、召回率和 Fβ 分数。
- 对所有类别的 Fβ 分数取平均值。
-
Micro 方法:
- 首先将所有类别的 TP、FP 和 FN 合并,计算总体的精确度、召回率和 Fβ 分数。
from sklearn.metrics import precision_recall_fscore_support
def calculate_macro_f1(preds, labels):
"""
计算宏观 F1 分数(Macro F1)。
参数:
preds (torch.Tensor): 模型的预测结果,0 或 1。
labels (torch.Tensor): 真实标签,0 或 1。
返回:
float: 宏观 F1 分数。
"""
precision, recall, f1, _ = precision_recall_fscore_support(labels.numpy(), preds.numpy(), average='macro')
return f1
# 示例
import torch
preds = torch.tensor([1, 0, 1, 1, 0])
labels = torch.tensor([1, 0, 0, 1, 1])
macro_f1 = calculate_macro_f1(preds, labels)
print(f"Macro F1 Score: {macro_f1:.2f}")
precision_recall_fscore_support
是 scikit-learn
提供的函数,它可以计算精确度、召回率和 F1 分数,并通过 average
参数来选择宏观或微观计算方式。
PR曲线
PR 曲线(Precision-Recall Curve)是一种评估分类模型性能的图形工具,特别适用于处理不平衡数据集。PR 曲线描绘了模型在不同决策阈值下的精确度(Precision)和召回率(Recall)的关系。
PR 曲线的定义
- 精确度(Precision):真正正类样本数与所有被预测为正类样本数的比例。
- 召回率(Recall):真正正类样本数与所有真实正类样本数的比例。
PR 曲线通常是通过在不同的阈值下计算精确度和召回率来绘制的,横轴表示召回率(Recall),纵轴表示精确度(Precision)。
在 Python 中,可以使用 scikit-learn
库绘制 PR 曲线。
import matplotlib.pyplot as plt
from sklearn.metrics import precision_recall_curve
from sklearn.metrics import average_precision_score
def plot_pr_curve(y_true, y_scores):
"""
绘制 PR 曲线(Precision-Recall Curve)。
参数:
y_true (list or numpy array): 真实标签,0 或 1。
y_scores (list or numpy array): 模型的预测分数或概率。
"""
precision, recall, _ = precision_recall_curve(y_true, y_scores)
average_precision = average_precision_score(y_true, y_scores)
plt.figure(figsize=(8, 6))
plt.plot(recall, precision, marker='.')
plt.title(f'PR Curve (Average Precision: {average_precision:.2f})')
plt.xlabel('Recall')
plt.ylabel('Precision')
plt.grid()
plt.show()
# 示例数据
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
# 生成示例数据
X, y = make_classification(n_samples=1000, n_features=20, n_classes=2, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# 训练模型
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
model = LogisticRegression()
model.fit(X_train_scaled, y_train)
# 获取模型预测概率
y_scores = model.predict_proba(X_test_scaled)[:, 1]
# 绘制 PR 曲线
plot_pr_curve(y_test, y_scores)
precision_recall_curve
:计算不同阈值下的精确度和召回率。average_precision_score
:计算平均精确度,用于量化整个 PR 曲线的性能。
PR 曲线和平均精确度(Average Precision, AP)提供了模型在所有可能的阈值下的综合性能指标,尤其在处理正负样本不平衡时非常有用。
-
初始化混淆矩阵计数:在
get_confusion_matrix
函数中,初始化 TP、FP、TN 和 FN 时不应设置为固定值,而是应从零开始计算。 -
改进
get_pr_pairs
函数:在每个阈值下计算精确度(Precision)和召回率(Recall),需要确保所有阈值都被处理,并避免冗余计算。 -
绘制 PR 曲线:在绘制时应确保曲线显示正确,且包含合理的标签和标题。
from typing import List, Tuple
import matplotlib.pyplot as plt
def get_confusion_matrix(
y_pred: List[int],
y_true: List[int]
) -> Tuple[int, int, int, int]:
tp, fp, tn, fn = 0, 0, 0, 0
for i in range(len(y_pred)):
if y_pred[i] == 1 and y_true[i] == 1:
tp += 1
elif y_pred[i] == 1 and y_true[i] == 0:
fp += 1
elif y_pred[i] == 0 and y_true[i] == 1:
fn += 1
elif y_pred[i] == 0 and y_true[i] == 0:
tn += 1
return (tp, fp, tn, fn)
def calc_p(tp: int, fp: int) -> float:
return tp / (tp + fp) if (tp + fp) > 0 else 0
def calc_r(tp: int, fn: int) -> float:
return tp / (tp + fn) if (tp + fn) > 0 else 0
def get_pr_pairs(
y_pred_prob: List[float],
y_true: List[int]
) -> Tuple[List[float], List[float]]:
thresholds = sorted(set(y_pred_prob), reverse=True)
ps = []
rs = []
for threshold in thresholds:
y_pred_i = [1 if prob >= threshold else 0 for prob in y_pred_prob]
tp, fp, tn, fn = get_confusion_matrix(y_pred_i, y_true)
p = calc_p(tp, fp)
r = calc_r(tp, fn)
ps.append(p)
rs.append(r)
ps.append(0)
rs.append(1)
return rs, ps
# 示例数据
y_pred_prob = [0.9, 0.8, 0.7, 0.6, 0.55, 0.54, 0.53, 0.52, 0.51, 0.505,
0.4, 0.39, 0.38, 0.37, 0.36, 0.35, 0.34, 0.33, 0.3, 0.1]
y_true = [1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0]
# 计算 PR 曲线
rs, ps = get_pr_pairs(y_pred_prob, y_true)
# 绘制 PR 曲线
fig, ax = plt.subplots(figsize=(12, 5))
ax.plot(rs, ps, marker='.')
ax.set_xlabel('Recall')
ax.set_ylabel('Precision')
ax.set_title('Precision-Recall Curve')
ax.grid(True)
plt.show()
-
get_confusion_matrix
函数:初始化 TP、FP、TN 和 FN 为 0,并在循环中计算真实的 TP、FP、TN 和 FN。 -
get_pr_pairs
函数:先按概率排序,并遍历每个阈值来计算精确度和召回率。使用set
和sorted
去除重复的阈值。 -
绘图:为 PR 曲线添加了标签和标题,使图形更具可读性。
置信度
置信度(Confidence)在机器学习和统计中通常指的是模型对其预测结果的确定程度。对于分类模型而言,置信度通常表示模型预测为某个类别的概率。这种概率表示了模型对某一预测的信心水平。
置信度的定义和应用
-
分类任务中的置信度:
- 在分类问题中,模型通常会输出每个类别的预测概率。例如,对于一个二分类问题,模型可能会输出一个概率值,例如 0.85,表示模型认为该样本属于正类的置信度为 85%。
- 置信度可以用来选择分类阈值,决定是否将样本分配给某个特定的类别。
-
置信度区间:
- 在统计学中,置信度也用来表示估计值的可靠性。一个 95% 的置信度区间意味着如果重复实验很多次,有 95% 的概率区间会包含真实的参数值。
置信度的计算和使用
在机器学习中,置信度通常由模型的输出概率计算得出。以一个简单的示例为例,假设我们有一个分类模型,它给出每个样本的预测概率。可以使用这些概率作为置信度来绘制 ROC 或 PR 曲线,或用于阈值选择。
import torch
import torch.nn.functional as F
def calculate_confidence(logits: torch.Tensor) -> torch.Tensor:
"""
计算预测的置信度。
参数:
logits (torch.Tensor): 模型的输出,未经归一化的 logits。
返回:
torch.Tensor: 预测的置信度。
"""
probabilities = F.softmax(logits, dim=1)
confidence, _ = torch.max(probabilities, dim=1)
return confidence
# 示例数据
logits = torch.tensor([[2.0, 1.0], [0.5, 1.5], [1.0, 1.0]])
confidence = calculate_confidence(logits)
print(f"Confidence: {confidence.tolist()}")
一般来说,置信度的定义与模型输出的概率密切相关,但你可以根据应用场景和需求自定义置信度的计算方式。以下是一些常见的自定义置信度的方法:
-
基于概率的置信度:
- 直接使用预测概率:如
predict_proba
方法返回的概率值直接作为置信度。高概率值通常表示高置信度。 - 阈值调整:你可以设置一个概率阈值,只有当模型的输出概率高于这个阈值时,才认为预测有较高置信度。
- 直接使用预测概率:如
-
加权置信度:
- 结合多个模型的置信度:在集成学习中,可以通过加权平均的方法来综合多个模型的置信度。
- 考虑模型不确定性:可以结合模型的不确定性度量(如预测的方差)来调整置信度。
-
基于后处理的置信度:
- 置信度调整:对预测概率进行额外的调整,例如使用校准技术(如 Platt 校准或 isotonic 校准)来提高置信度的可靠性。
-
应用特定的置信度度量:
- 在特定领域中定义置信度:例如在医学图像分析中,置信度可能不仅仅基于预测概率,还可能结合其他指标如图像质量、模型对特定特征的响应等。
-
自定义置信度函数:
- 你可以定义一个函数来计算置信度,这个函数可以根据模型的输出、样本特征和领域知识进行调整。
常用的求置信度的函数主要取决于具体的应用场景和模型。以下是一些常见的求置信度的方法和函数:
1. 预测概率作为置信度
对于许多模型,预测概率本身可以作为置信度。大多数分类模型提供 predict_proba
方法来获取每个类的概率。
-
逻辑回归(Logistic Regression):
from sklearn.linear_model import LogisticRegression
model = LogisticRegression()
model.fit(X_train, y_train)
probabilities = model.predict_proba(X_test)
confidence = probabilities[:, 1] # 对于二分类问题,取正类的概率作为置信度
- 随机森林(Random Forest):
from sklearn.ensemble import RandomForestClassifier
model = RandomForestClassifier()
model.fit(X_train, y_train)
probabilities = model.predict_proba(X_test)
confidence = probabilities[:, 1] # 对于二分类问题
2. 置信度校准
为了提高置信度的可靠性,可以使用校准技术。例如,Platt 校准或 Isotonic 校准可以调整模型输出的概率,使其更符合真实的置信度。
-
Platt 校准:
from sklearn.calibration import CalibratedClassifierCV from sklearn.linear_model import LogisticRegression model = LogisticRegression() model.fit(X_train, y_train) # 使用 Platt 校准 calibrated_model = CalibratedClassifierCV(model, method='sigmoid') calibrated_model.fit(X_train, y_train) probabilities = calibrated_model.predict_proba(X_test) confidence = probabilities[:, 1]
-
Isotonic 校准:
from sklearn.calibration import CalibratedClassifierCV from sklearn.ensemble import RandomForestClassifier model = RandomForestClassifier() model.fit(X_train, y_train) # 使用 Isotonic 校准 calibrated_model = CalibratedClassifierCV(model, method='isotonic') calibrated_model.fit(X_train, y_train) probabilities = calibrated_model.predict_proba(X_test) confidence = probabilities[:, 1]
3. 置信度评分函数
一些库和方法提供了专门的置信度评分函数来评估模型的置信度。以下是一些示例:
sklearn
中的predict_proba
: 返回类别的概率分布,可以直接作为置信度。tensorflow
/keras
中的predict
: 在神经网络模型中,predict
方法返回每个样本的类概率。
4. 自定义置信度函数
你可以定义自己的置信度函数,根据应用场景的需求来计算置信度。
def custom_confidence(probabilities, factor=1.0):
return probabilities[:, 1] * factor
# 使用自定义置信度函数
confidence = custom_confidence(probabilities, factor=1.2)
5. 置信区间和不确定性量度
在某些高级应用中,置信度也可以通过模型的不确定性量度来评估,例如通过蒙特卡罗 dropout 或贝叶斯方法。
- 蒙特卡罗 Dropout:
import tensorflow as tf from tensorflow.keras.models import Model def mc_dropout_predict(model, X, n_samples=100): predictions = np.zeros((n_samples, X.shape[0], model.output_shape[-1])) for i in range(n_samples): predictions[i] = model(X, training=True).numpy() return predictions.mean(axis=0), predictions.std(axis=0) # 使用蒙特卡罗 Dropout 计算置信度 mean_predictions, uncertainty = mc_dropout_predict(model, X_test) confidence = 1 - uncertainty.mean(axis=1) # 例如使用不确定性的均值作为置信度
IOU
IOU(Intersection over Union),雅卡尔指数( Jaccard index),交并比,是一种常用的评估指标,用于衡量两个区域(如预测框和真实框)之间的重叠程度。IOU 在目标检测和分割任务中尤为重要,用于评估模型的预测框或分割区域的准确性。
IOU 的定义
IOU 是预测框与真实框的交集面积与它们的并集面积的比值。公式如下:
其中:
- Intersection(交集):预测框和真实框重叠的区域面积。
- Union(并集):预测框和真实框合并的区域面积。
计算 IOU 的步骤
- 计算交集面积:预测框和真实框重叠区域的面积。
- 计算并集面积:预测框和真实框的总面积减去交集面积。
- 计算 IOU:用交集面积除以并集面积。
import torch
def calculate_iou(box1, box2):
"""
计算两个矩形框的 IOU。
参数:
box1 (torch.Tensor): 第一个框的坐标 (x1, y1, x2, y2)。
box2 (torch.Tensor): 第二个框的坐标 (x1, y1, x2, y2)。
返回:
float: 两个框的 IOU。
"""
# 计算交集区域的坐标
x1_inter = max(box1[0], box2[0])
y1_inter = max(box1[1], box2[1])
x2_inter = min(box1[2], box2[2])
y2_inter = min(box1[3], box2[3])
# 计算交集的面积
inter_area = max(0, x2_inter - x1_inter) * max(0, y2_inter - y1_inter)
# 计算两个框的面积
box1_area = (box1[2] - box1[0]) * (box1[3] - box1[1])
box2_area = (box2[2] - box2[0]) * (box2[3] - box2[1])
# 计算并集的面积
union_area = box1_area + box2_area - inter_area
# 计算 IOU
iou = inter_area / union_area if union_area > 0 else 0.0
return iou
# 示例
box1 = torch.tensor([1, 1, 4, 4], dtype=torch.float32) # (x1, y1, x2, y2)
box2 = torch.tensor([2, 2, 5, 5], dtype=torch.float32) # (x1, y1, x2, y2)
iou = calculate_iou(box1, box2)
print(f"IOU: {iou:.2f}")
- 交集区域:使用最大和最小坐标计算两个框的重叠部分。
- 并集区域:计算两个框的总面积减去交集面积。
- IOU:用交集面积除以并集面积。
IOU 在目标检测中通常用于筛选预测框或评估模型的预测效果。常见的做法是设定一个 IOU 阈值,例如 0.5,用于确定一个预测框是否与真实框匹配。
一般情况下在目标检测任务中,人们将IOU ≥0.7时判定为正样本,其余情况判定为负样本。
AP
AP(Average Precision) 是用于评估目标检测和信息检索任务中模型性能的重要指标。AP 综合了精确度(Precision)和召回率(Recall),特别是在不同的置信度阈值下进行评估。
AP 的定义
AP 是精确度和召回率之间的关系的综合度量,通常通过绘制 PR 曲线(Precision-Recall Curve) 并计算其下面积来获得。
计算 AP 的步骤
-
计算 PR 曲线:
- 在不同的置信度阈值下计算模型的精确度和召回率。
-
计算 AP:
- 通过对 PR 曲线下的面积进行积分,得到 AP。对于每一个召回率值,计算对应的精确度,然后对这些精确度取平均值,得到 AP。
常用的 AP 计算方法
-
11 点插值(11-point interpolation):
- 在 0 到 1 的召回率范围内,以 0.0、0.1、0.2、…、1.0 为步长计算精确度,然后对这些精确度进行平均。
-
平滑 AP:
- 使用更多的召回率点(例如 101 个点)进行计算,得到更平滑的 AP 曲线。
import torch
from sklearn.metrics import precision_recall_curve, average_precision_score
import numpy as np
def calculate_ap(pred_probs, true_labels):
"""
计算平均精确度(AP)。
参数:
pred_probs (torch.Tensor): 模型的预测概率(通常是 softmax 的输出)。
true_labels (torch.Tensor): 真实标签(0 或 1)。
返回:
float: 平均精确度(AP)。
"""
# 将 PyTorch 张量转换为 numpy 数组
pred_probs_np = pred_probs.numpy()
true_labels_np = true_labels.numpy()
# 计算精确度和召回率
precision, recall, _ = precision_recall_curve(true_labels_np, pred_probs_np)
# 计算平均精确度(AP)
ap = average_precision_score(true_labels_np, pred_probs_np)
return ap
# 示例
pred_probs = torch.tensor([0.9, 0.2, 0.8, 0.6, 0.4], dtype=torch.float32)
true_labels = torch.tensor([1, 0, 1, 1, 0], dtype=torch.float32)
ap = calculate_ap(pred_probs, true_labels)
print(f"Average Precision (AP): {ap:.2f}")
precision_recall_curve
:计算不同置信度下的精确度和召回率。average_precision_score
:计算 PR 曲线下的面积,即 AP。
AP 是评估目标检测模型性能的关键指标,特别是当数据集具有类不平衡或多类别问题时,它可以提供对模型综合性能的深入了解。在 COCO 和 PASCAL VOC 等挑战中,AP 是常用的评价标准。
mAP
mAP(mean Average Precision) 是一种常用于评估目标检测和信息检索任务中模型性能的综合指标。它是对所有类别的平均精确度(AP)的平均值,用于总结模型在不同类别上的表现。
mAP 的计算步骤:
-
计算每个类别的 AP:
- 对于每个类别,计算其精确度-召回率(PR)曲线,并求出该曲线下的面积,即 Average Precision(AP)。
-
计算 mAP:
- 对所有类别的 AP 取平均值,得到 mean Average Precision(mAP)。
import numpy as np
from sklearn.metrics import average_precision_score
def calculate_ap(pred_probs, true_labels):
"""
计算平均精确度(AP)。
参数:
pred_probs (numpy.ndarray): 模型的预测概率。
true_labels (numpy.ndarray): 真实标签。
返回:
float: 平均精确度(AP)。
"""
return average_precision_score(true_labels, pred_probs)
def calculate_map(pred_probs_list, true_labels_list):
"""
计算平均平均精确度(mAP)。
参数:
pred_probs_list (list of numpy.ndarray): 每个类别的预测概率。
true_labels_list (list of numpy.ndarray): 每个类别的真实标签。
返回:
float: 平均平均精确度(mAP)。
"""
ap_list = []
for pred_probs, true_labels in zip(pred_probs_list, true_labels_list):
ap = calculate_ap(pred_probs, true_labels)
ap_list.append(ap)
map_score = np.mean(ap_list)
return map_score
# 示例数据(假设有三个类别)
pred_probs_list = [
np.array([0.9, 0.8, 0.7]), # 类别 1 的预测概率
np.array([0.4, 0.6, 0.5]), # 类别 2 的预测概率
np.array([0.7, 0.2, 0.9]) # 类别 3 的预测概率
]
true_labels_list = [
np.array([1, 1, 0]), # 类别 1 的真实标签
np.array([0, 1, 0]), # 类别 2 的真实标签
np.array([1, 0, 1]) # 类别 3 的真实标签
]
map_score = calculate_map(pred_probs_list, true_labels_list)
print(f"Mean Average Precision (mAP): {map_score:.2f}")
三、常用包Numpy、pandas、matplotlib
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# NumPy 示例
array = np.array([1, 2, 3, 4, 5])
mean_value = np.mean(array)
# pandas 示例
df = pd.DataFrame({
'X': [1, 2, 3, 4, 5],
'Y': [1, 4, 9, 16, 25]
})
df['Z'] = df['X'] + df['Y']
# matplotlib 示例
plt.figure(figsize=(10, 5))
plt.subplot(1, 2, 1)
plt.plot(df['X'], df['Y'], marker='o')
plt.title('Line Plot')
plt.xlabel('X')
plt.ylabel('Y')
plt.subplot(1, 2, 2)
plt.scatter(df['X'], df['Z'])
plt.title('Scatter Plot')
plt.xlabel('X')
plt.ylabel('Z')
plt.tight_layout()
plt.show()
Numpy
参考官方文档:NumPy 快速入门 — NumPy v2.0 手册 - NumPy 中文
NumPy 是一个 Python 库,提供了对多维数组对象和多种数值计算功能的支持,是数据科学和机器学习中常用的基础包。它提供了高效的数组操作、数学函数、线性代数运算、统计分析等功能。
NumPy 的主要对象是同构多维数组。它是一个元素表(通常是数字),所有元素类型相同,由非负整数元组索引。在 NumPy 中,维度称为轴。
常用功能和函数
创建数组:
np.array()
: 从列表或元组创建数组。np.zeros()
: 创建全零数组。np.ones()
: 创建全一数组。np.arange()
: 创建具有指定范围的数组。np.linspace()
: 创建具有指定范围和步长的数组。np.empty()
: 创建未初始化的数组。
import numpy as np
# 创建数组
array = np.array([1, 2, 3, 4, 5])
print("Original Array:", array)
# 数组操作
print("Shape:", array.shape)
print("Reshaped Array:", array.reshape((1, 5)))
# 数学运算
print("Array + 10:", array + 10)
print("Array * 2:", array * 2)
print("Mean:", np.mean(array))
# 随机数生成
random_array = np.random.rand(2, 2)
print("Random Array:\n", random_array)
# 矩阵运算
matrix = np.array([[1, 2], [3, 4]])
print("Matrix:\n", matrix)
print("Matrix Product:\n", np.dot(matrix, matrix))
# 保存和加载
np.save('matrix.npy', matrix)
loaded_matrix = np.load('matrix.npy')
print("Loaded Matrix:\n", loaded_matrix)
pandas
pandas 是一个用于数据操作和分析的库,提供了高效的数据结构,如 DataFrame 和 Series。
创建 DataFrame 和 Series:
import pandas as pd
# 创建 DataFrame
df = pd.DataFrame({
'A': [1, 2, 3],
'B': [4, 5, 6]
})
# 创建 Series
series = pd.Series([1, 2, 3, 4])
数据操作:
# 数据筛选
filtered_df = df[df['A'] > 1]
# 数据排序
sorted_df = df.sort_values(by='A')
# 缺失值处理
df_filled = df.fillna(0)
数据读写:
# 读取 CSV 文件
df = pd.read_csv('data.csv')
# 保存为 CSV 文件
df.to_csv('output.csv', index=False)
数据聚合:
# 分组操作
grouped_df = df.groupby('A').sum()
matplotlib
matplotlib 是一个绘图库,用于创建静态、动态和交互式的图形。
Axes
轴是附加到图形的艺术家,它包含一个用于绘制数据的区域,并且通常包括两个(或在 3D 的情况下为三个)Axis 对象(注意轴和轴线之间的差异),它们提供刻度和刻度标签,以便为轴中的数据提供刻度。每个Axes 还有一个标题(通过 set_title() 设置),一个 x 标签(通过 set_xlabel() 设置),和一个通过 set_ylabel() 设置的 y 标签。
Axes 方法是配置绘图大部分内容(添加数据、控制轴刻度和限制、添加标签等)的主要接口。
Axis
这些对象设置比例和限制,并生成刻度(轴上的标记)和刻度标签(标记刻度的字符串)。刻度的定位由 Locator 对象确定,刻度标签字符串由 Formatter 格式化。正确的 Locator 和 Formatter 组合可以非常精细地控制刻度位置和标签。
Artist
基本上,图形上可见的所有内容都是 Artist(甚至 Figure、Axes 和 Axis 对象)。这包括 Text 对象、Line2D 对象、collections 对象、Patch 对象等。在渲染图形时,所有 Artist 都会绘制到画布上。大多数 Artist 都与 Axes 绑定;此类 Artist 不能由多个 Axes 共享,也不能从一个 Axes 移动到另一个 Axes。
使用 Matplotlib 进行动画
基于其绘图功能,Matplotlib 还提供了一个使用 animation 模块生成动画的接口。动画是一系列帧,其中每一帧对应于 Figure 上的绘图。本教程涵盖了有关如何创建此类动画以及可用不同选项的一般指南。
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.animation as animation
动画类
Matplotlib 中的动画过程可以从 2 种不同的方式来考虑
-
FuncAnimation: 生成第一帧的数据,然后修改此数据以创建动画绘图。
-
ArtistAnimation: 生成一个艺术家列表(可迭代的),这些艺术家将在动画中的每一帧中绘制。
FuncAnimation 在速度和内存方面更有效,因为它只绘制一次艺术家,然后对其进行修改。另一方面,ArtistAnimation 很灵活,因为它允许任何艺术家可迭代对象按顺序进行动画处理。
FuncAnimation
FuncAnimation 类允许我们通过传递一个迭代修改绘图数据的函数来创建动画。 这是通过使用各种 Artist (例如:Line2D,PathCollection 等)的 *setter* 方法来实现的。 一个典型的 FuncAnimation 对象接受一个我们想要动画化的 Figure 和一个修改绘图上数据的函数 *func*。 它使用 *frames* 参数来确定动画的长度。 *interval* 参数用于确定两帧之间绘制的时间(以毫秒为单位)。 使用 FuncAnimation 进行动画制作通常需要以下步骤
-
像在静态绘图中一样绘制初始图形。 将所有创建的艺术家(由绘图函数返回)保存在变量中,以便您以后在动画函数中访问和修改它们。
-
创建一个动画函数,该函数更新给定帧的艺术家。 通常,这会调用艺术家的
set_*
方法。 -
创建一个 FuncAnimation,传递 Figure 和动画函数。
-
使用以下方法之一保存或显示动画
-
pyplot.show 在窗口中显示动画
-
Animation.to_html5_video 创建一个 HTML
<video>
标签 -
Animation.to_jshtml 用于创建带有交互式 JavaScript 动画控件的 HTML 代码
-
Animation.save 用于将动画保存到文件
-
ArtistAnimation
ArtistAnimation 可用于生成动画,前提是数据存储在不同的艺术家对象上。然后,这些艺术家对象的列表逐帧转换为动画。例如,当我们使用 Axes.barh 绘制条形图时,它会为每个条形和误差线创建多个艺术家对象。要更新绘图,需要单独更新容器中的每个条形并重新绘制它们。相反,animation.ArtistAnimation 可用于单独绘制每一帧,然后将它们拼接在一起形成动画。条形图竞赛就是一个简单的例子。
动画写入器
动画对象可以使用各种多媒体写入器(例如:Pillow、ffpmeg、imagemagick)保存到磁盘。并非所有视频格式都受所有写入器支持。主要有四种类型的写入器。
-
PillowWriter - 使用 Pillow 库创建动画。
-
HTMLWriter - 用于创建基于 JavaScript 的动画。
-
基于管道的写入器 - FFMpegWriter 和 ImageMagickWriter 是基于管道的写入器。这些写入器将每一帧管道传输到实用程序(ffmpeg / imagemagick),然后将所有帧拼接在一起以创建动画。
-
基于文件的写入器 - FFMpegFileWriter 和 ImageMagickFileWriter 是基于文件的写入器的示例。这些写入器比基于管道的写入器速度慢,但对于调试更有用,因为它们会在将帧拼接成动画之前将每一帧保存到文件中。
要使用任何编写器保存动画,我们可以使用 animation.Animation.save 方法。它接受我们要保存动画的文件名和编写器,编写器可以是字符串或编写器对象。它还接受一个fps参数。此参数与 FuncAnimation 或 ArtistAnimation 使用的interval参数不同。fps决定保存的动画使用的帧速率,而interval决定显示的动画使用的帧速率。
举例:
绘制基本图形:
import matplotlib.pyplot as plt
# 绘制线图
x = [1, 2, 3, 4, 5]
y = [1, 4, 9, 16, 25]
plt.plot(x, y)
plt.title('Line Plot')
plt.xlabel('X Axis')
plt.ylabel('Y Axis')
plt.show()
# 绘制散点图
plt.scatter(x, y)
plt.title('Scatter Plot')
plt.xlabel('X Axis')
plt.ylabel('Y Axis')
plt.show()
绘制直方图:
data = [1, 2, 2, 3, 4, 4, 4, 5, 6]
plt.hist(data, bins=5)
plt.title('Histogram')
plt.xlabel('Bins')
plt.ylabel('Frequency')
plt.show()
绘制子图:
plt.subplot(1, 2, 1)
plt.plot(x, y)
plt.title('Line Plot')
plt.subplot(1, 2, 2)
plt.scatter(x, y)
plt.title('Scatter Plot')
plt.show()
四、Jupyter notebook/Lab 简述
安装
conda create -n pytorch python=3.8 ipykernel
conda activate pytorch
conda install jupyter notebook
conda install -c conda-forge jupyterlab
jupyter notebook # 打开Jupyter Notebook
jupyter lab