缺失值的处理方法大总结

一.缺失的原因

缺失值是指粗糙数据中由于缺少信息而造成的数据的聚类、分组、删失或截断。它指的是现有数据集中某个或某些属性的值是不完全的。缺失值的产生的原因多种多样,主要分这几个原因:

  • 无意的:信息被遗漏,比如由于工作人员的疏忽,忘记而缺失;或者由于数据采集 器等故障等原因造成的缺失,比如系统实时性要求较高的时候,机器来不及判断和决策而造成缺失;
  • 有意的:有些数据集在特征描述中会规定将缺失值也作为一种特征值,这时候缺失值就可以看作是一种特殊的特征值;
  • 不存在:有些特征属性根本就是不存在的,比如一个未婚者的配偶名字就没法填写,再如一个孩子的收入状况也无法填写;

二.数据缺失的类型

在对缺失数据进行处理前,了解数据缺失的机制和形式是十分必要的。将数据集中不含缺失值的变量称为完全变量,数据集中含有缺失值的变量称为不完全变量。而从缺失的分布来将缺失可以分为完全随机缺失,随机缺失和完全非随机缺失。

  • 完全随机缺失(missing completely at random,MCAR):指的是数据的缺失是完全随机的,不依赖于任何不完全变量或完全变量,不影响样本的无偏性,如家庭地址缺失;
  • 随机缺失(missing at random,MAR):指的是数据的缺失不是完全随机的,即该类数据的缺失依赖于其他完全变量,如财务数据缺失情况与企业的大小有关;
  • 非随机缺失(missing not at random,MNAR):指的是数据的缺失与不完全变量自身的取值有关,如高收入人群不原意提供家庭收入;

对于随机缺失和非随机缺失,直接删除记录是不合适的,原因上面已经给出。随机缺失可以通过已知变量对缺失值进行估计,而非随机缺失的非随机性还没有很好的解决办法。

三.缺失值的处理方法

缺失值的一般处理方法有三种:删除,填补,不处理。

1. 删除

此方法将存在缺失值的数据条目(对象,元组,记录)进行删除。

dropna()

可以利用pandas的dropna()函数进行删除。
举个栗子:

import numpy as np
import pandas as pd

df = pd.DataFrame([[1, np.nan, 2], [2, 3, 5], [np.nan, 4, 6]])
df1 = df.dropna()
print(df)
print('-------')
print(df1)

结果:

     0    1  2
0  1.0  NaN  2
1  2.0  3.0  5
2  NaN  4.0  6
-------
     0    1  2
1  2.0  3.0  5

需要注意的是,dropna() 在默认情况下会剔除任何包含缺失值的整数据。可以设置按不同的坐标轴剔除缺失值,比如 axis=1(或 axis=‘columns’)会剔除任何包含缺失值的整列数据:

import numpy as np
import pandas as pd

df = pd.DataFrame([[1, np.nan, 2], [2, 3, 5], [np.nan, 4, 6]])
df1 = df.dropna(axis=1)
print(df)
print('-------')
print(df1)

结果:

     0    1  2
0  1.0  NaN  2
1  2.0  3.0  5
2  NaN  4.0  6
-------
   2
0  2
1  5
2  6

按照上述做法会把非缺失值一并剔除,而有时候只需要剔除全部是缺失值的行或列,或者绝大多数是缺失值的行或列。这些需求可以通过设置 how 或 thresh 参数来满足, 它们可以设置剔除行或列缺失值的数量阈值。

默认设置是 how=‘any’,也就是说只要有缺失值就剔除整行或整列(通过 axis 设置坐标轴)。你还可以设置 how=‘all’,这样就只会剔除全部是缺失值的行或列了:

df[3] = np.nan
df1 = df.dropna(axis=1, how='all')
print(df)
print('-------')
print(df1)

结果:

     0    1  2   3
0  1.0  NaN  2 NaN
1  2.0  3.0  5 NaN
2  NaN  4.0  6 NaN
-------
     0    1  2
0  1.0  NaN  2
1  2.0  3.0  5
2  NaN  4.0  6

还可以通过 thresh 参数设置行或列中非缺失值的最小数量,从而实现更加个性化的配置:

通过axis=0, thresh=3,实现删除非缺失值不为3个的行。

df = pd.DataFrame([[1, np.nan, 2], [2, 3, 5], [np.nan, 4, 6]])
df1 = df.dropna(axis=0, thresh=3)
print(df)
print('-------')
print(df1)

结果:

     0    1  2
0  1.0  NaN  2
1  2.0  3.0  5
2  NaN  4.0  6
-------
     0    1  2
1  2.0  3.0  5

缺点

直接删除会有一些缺点:

  • 牺牲了大量的数据,通过减少历史数据换取完整的信息,这样可能丢失了很多隐藏的重要信息;
  • 当缺失数据比例较大时,特别是缺失数据非随机分布时,直接删除可能会导致数据发生偏离,比如原本的正态分布变为非正太;

2.填补

对缺失值的填补大体可分为三种:替换缺失值,拟合缺失值,虚拟变量。替换是通过数据中非缺失数据的相似性来填补,其核心思想是发现相同群体的共同特征,拟合是通过其他特征建模来填补,虚拟变量是衍生的新变量代替缺失值。

替换缺失值

均值填充

对于数值型数据:使用 众数(mode)填补,比如一个学校的男生和女生的数量,男生500人,女生50人,那么对于其余的缺失值我们会用人数较多的男生来填补。

对于非数值型数据:使用平均数(mean)或中位数(median)填补,比如一个班级学生的身高特征,对于一些同学缺失的身高值就可以使用全班同学身高的平均值或中位数来填补。一般如果特征分布为正太分布时,使用平均值效果比较好,而当分布由于异常值存在而不是正太分布的情况下,使用中位数效果比较好。

用pandas的fillna()可以进行填充:
举个栗子,中均值填充:

df = pd.DataFrame([[1, np.nan, 2], [2, 3, 5], [np.nan, 4, 6]])
df.iloc[:, 0] = df.iloc[:, 0].fillna(df.iloc[:, 0].mean())
print(df)

结果:

     0    1  2
0  1.0  NaN  2
1  2.0  3.0  5
2  1.5  4.0  6

也可以用众数填充:

df = pd.DataFrame([[1, np.nan, 2], [1, 3, 5], [np.nan, 4, 6]])
df.iloc[:, 0] = df.iloc[:, 0].fillna(df.iloc[:, 0].median())
print(df)

结果:

     0    1  2
0  1.0  NaN  2
1  1.0  3.0  5
2  1.0  4.0  6

或者用众数:

df = pd.DataFrame([[1, np.nan, 2], [1, 3, 5], [np.nan, 4, 6]])
df.iloc[:, 0] = df.iloc[:, 0].fillna(df.iloc[:, 0].mode()[0])
print(df)

结果:

     0    1  2
0  1.0  NaN  2
1  1.0  3.0  5
2  1.0  4.0  6
热卡填补

热卡填充法是在完整数据中找到一个与它最相似的对象,然后用这个相似对象的值来进行填充。通常会找到超出一个的相似对象,在所有匹配对象中没有最好的,而是从中随机的挑选一个作为填充值。这个问题关键是不同的问题可能会选用不同的标准来对相似进行判定,以及如何制定这个判定标准。该方法概念上很简单,且利用了数据间的关系来进行空值估计,但缺点在于难以定义相似标准,主观因素较多。

K均值

利用无监督机器学习的聚类方法,通过K均值的聚类方法将所有样本进行聚类划分,然后再通过划分的种类的均值对各自类中的缺失值进行填补。归其本质还是通过找相似来填补缺失值。一般先根据欧式距离或相关分析来确定距离具有缺失数据样本最近的K个样本,将这K个值加权平均来估计该样本的缺失数据。

拟合缺失值

拟合就是利用其它变量做模型的输入进行缺失变量的预测,与我们正常建模的方法一样,只是目标变量变为了缺失值。

注意如果其它特征变量与缺失变量无关,则预测的结果毫无意义。如果预测结果相当准确,则又说明这个变量完全没有必要进行预测,因为这必然是与特征变量间存在重复信息。一般情况下,会介于两者之间效果为最好,若强行填补缺失值之后引入了自相关,这会给后续分析造成障碍。

利用模型预测缺失变量的方法有很多,这里仅简单介绍几种。

回归预测

基于完整的数据集,建立回归方程(模型)。对于包含空值的对象,将已知属性值代入方程来估计未知属性值,以此估计值来进行填充。当变量不是线性相关或预测变量高度相关时会导致有偏差的估计。

极大似然估计

在缺失类型为随机缺失的条件下,假设模型对于完整的样本是正确的,那么通过观测数据的边际分布可以对未知参数进行极大似然估计(Little and Rubin)。这种方法也被称为忽略缺失值的极大似然估计,对于极大似然的参数估计实际中常采用的计算方法是期望值最大化(Expectation Maximization,EM)。该方法比删除个案和单值插补更有吸引力,它一个重要前提:适用于大样本。有效样本的数量足够以保证ML估计值是渐近无偏的并服从正态分布。但是这种方法可能会陷入局部极值,收敛速度也不是很快,并且计算很复杂,且仅限于线性模型。

多重插补

多值插补的思想来源于贝叶斯估计,认为待插补的值是随机的,它的值来自于已观测到的值。具体实践上通常是估计出待插补的值,然后再加上不同的噪声,形成多组可选插补值。根据某种选择依据,选取最合适的插补值。

我们看到,以上提出的拟合和替换方法都是单一的插补方法,而多重插补弥补了单一插补的缺陷,它并没有试图去通过模拟值去估计每个缺失值,而是提出缺失数据值的一个随即样本(这些样本可以是不同的模型拟合结果的组合)。这种程序的实施恰当地反映了由于缺失值引起的不确定性,使得统计有效。多重插补可以分为以下3个步骤:

  • 为每个缺失值产生一套可能的插补值,这些值反映了无响应模型的不确定性;
  • 每个插补数据集合都用针对完整数据集的统计方法进行统计分析;
  • 对来自各个插补数据集的结果,根据评分函数进行选择,产生最终的插补值;

根据数据缺失机制、模式以及变量类型,可分别采用回归、预测均数匹配( predictive mean matching, PMM )、趋势得分( propensity score, PS )、Logistic回归、判别分析以及马尔可夫链蒙特卡罗( Markov Chain Monte Carlo, MCMC) 等不同的方法进行填补。

假设一组数据,包括三个变量Y1,Y2,Y3,它们的联合分布为正态分布,将这组数据处理成三组,A组保持原始数据,B组仅缺失Y3,C组缺失Y1和Y2。在多值插补时,对A组将不进行任何处理,对B组产生Y3的一组估计值(作Y3关于Y1,Y2的回归),对C组作产生Y1和Y2的一组成对估计值(作Y1,Y2关于Y3的回归)。

当用多值插补时,对A组将不进行处理,对B、C组将完整的样本随机抽取形成为m组(m为可选择的m组插补值),每组个案数只要能够有效估计参数就可以了。对存在缺失值的属性的分布作出估计,然后基于这m组观测值,对于这m组样本分别产生关于参数的m组估计值,给出相应的预测,这时采用的估计方法为极大似然法,在计算机中具体的实现算法为期望最大化法(EM)。对B组估计出一组Y3的值,对C将利用Y1,Y2,Y3它们的联合分布为正态分布这一前提,估计出一组(Y1,Y2)。

上例中假定了Y1,Y2,Y3的联合分布为正态分布。这个假设是人为的,但是已经通过验证(Graham和Schafer于1999),非正态联合分布的变量,在这个假定下仍然可以估计到很接近真实值的结果。

注:使用多重插补要求数据缺失值为随机性缺失,一般重复次数20-50次精准度很高,但是计算也很复杂,需要大量计算。

随即森林

另一种比较常用的拟合方法就是随机森林,
举个栗子,在kaggle题目Titanic生存预测的缺失值处理时,用随机森林来填充缺失的Age。

from sklearn.ensemble import RandomForestRegressor

#choose training data to predict age
age_df = train_data[['Age','Survived','Fare', 'Parch', 'SibSp', 'Pclass']]
age_df_notnull = age_df.loc[(train_data['Age'].notnull())]
age_df_isnull = age_df.loc[(train_data['Age'].isnull())]
X = age_df_notnull.values[:,1:]
Y = age_df_notnull.values[:,0]
# use RandomForestRegression to train data
RFR = RandomForestRegressor(n_estimators=1000, n_jobs=-1)
RFR.fit(X,Y)
predictAges = RFR.predict(age_df_isnull.values[:,1:])
train_data.loc[train_data['Age'].isnull(), ['Age']]= predictAges

虚拟变量

虚拟变量其实就是缺失值的一种衍生变量。具体做法是通过判断特征值是否有缺失值来定义一个新的二分类变量。比如,特征为A含有缺失值,我们衍生出一个新的特征B,如果A中特征值有缺失,那么相应的B中的值为1,如果A中特征值没有缺失,那么相应的B中的值为0。

3.不处理

补齐处理只是将未知值补以我们的主观估计值,不一定完全符合客观事实,在对不完备信息进行补齐处理的同时,我们或多或少地改变了原始的信息系统。而且,对空值不正确的填充往往将新的噪声引入数据中,使挖掘任务产生错误的结果。因此,在许多情况下,我们还是希望在保持原始信息不发生变化的前提下对信息系统进行处理。

在实际应用中,一些模型无法应对具有缺失值的数据,因此要对缺失值进行处理。然而还有一些模型本身就可以应对具有缺失值的数据,此时无需对数据进行处理,比如Xgboost,rfr等高级模型。

四.总结

总而言之,大部分数据挖掘的预处理都会使用比较方便的方法来处理缺失值,比如均值法,但是效果上并一定好,因此还是需要根据不同的需要选择合适的方法,并没有一个解决所有问题的万能方法。具体的方法采用还需要考虑多个方面的:

  • 数据缺失的原因;
  • 数据缺失值类型;
  • 样本的数据量;
  • 数据缺失值随机性等;

五.参考资料

机器学习缺失值处理方法汇总
Pandas高级:你真的会删除缺失值吗?
【Python数据分析基础】: 数据缺失值处理

<think>好的,我现在需要回答用户关于YOLOv8如何处理缺失值的问题。首先,我得先理解用户的问题到底是什么。用户提到的“缺失值”可能指的是数据中的缺失情况,比如标注数据中的缺失标签或者图像中的部分缺失。不过,YOLOv8主要是用于目标检测的模型,通常处理的是图像和对应的边界框标注数据,所以在处理缺失值方面可能需要具体分析。 首先,我应该回顾一下YOLOv8的数据处理流程。YOLOv8在训练时,通常会加载标注文件,比如YOLO格式的.txt文件,每个文件对应一张图像,里面包含了该图像中所有目标的类别和边界框信息。如果某个图像的标注文件缺失,或者标注文件中的某些目标信息不完整,这时候就需要处理这些缺失值。 接下来,我需要查阅相关的文档或者源代码,看看YOLOv8是否有内置的处理机制。根据用户提供的引用内容,YOLOv8的模型可以通过不同的模式运行,如train、val、predict等,其中在训练时可能需要处理数据中的问题。比如在数据加载过程中,如果某个标注文件缺失,YOLOv8可能会跳过该图像或者采用某种替代策略。不过,用户提供的引用中并没有直接提到如何处理缺失值,因此可能需要进一步的推断或查找其他资料。 另外,用户提到的引用[2]中提到了YOLOv8在Python中的使用方式,包括加载模型、训练、验证、预测和导出。其中在训练时,使用model.train(data="coco128.yaml", epochs=3)。数据配置文件(如coco128.yaml)中通常包含训练和验证数据的路径、类别数等信息。也许在数据配置中,可以设置如何处理缺失值,比如忽略缺失标注的图像,或者使用数据增强来补充缺失的数据。 处理缺失值的常见方法可能包括: 1. **数据清洗**:在数据预处理阶段,检查并删除含有缺失值的样本。例如,如果某个图像没有对应的标注文件,或者标注文件格式错误,可以在加载数据时跳过这些样本。 2. **数据插补**:对于部分缺失的标注信息,比如某些目标的坐标缺失,可能需要根据上下文或其他信息进行合理的猜测,但这种方法在目标检测中不太常见,因为边界框的缺失会导致无法正确训练。 3. **数据增强**:通过随机裁剪、旋转、缩放等手段生成更多的训练样本,从而间接减少缺失值的影响,但这更多是针对数据量不足的情况,而非直接处理缺失值。 4. **使用默认值或忽略**:在模型训练过程中,如果遇到缺失的标注,可以选择忽略该目标或使用默认值填充,但需要确保模型能够正确处理这种情况。 在YOLOv8的实现中,可能通过数据加载器(DataLoader)来处理这些问题。例如,在加载数据集时,检查每个标注文件是否存在,格式是否正确,如果存在问题则跳过该样本。这通常在数据预处理阶段完成,可以通过自定义的数据加载逻辑来实现。 此外,用户可能需要了解如何在代码层面实现这些处理。例如,在自定义数据集类时,可以添加对缺失标注文件的检查,并在遇到时跳过或记录错误。或者,在数据增强阶段,使用某些技术来生成合理的数据,减少缺失带来的影响。 总结来说,YOLOv8本身可能没有专门处理缺失值的函数,但可以通过数据预处理和增强的方法来应对。用户需要根据具体情况,在数据准备阶段进行清洗或插补,确保输入到模型的数据是完整和有效的。同时,结合YOLOv8的数据配置和训练参数,调整模型训练过程以适应可能存在的数据缺失情况。</think>在YOLOv8中处理缺失值主要通过**数据预处理策略**和**模型训练优化**实现。以下是具体方法及实现技巧: --- ### 1. **数据清洗与过滤** - **原理**:在数据加载阶段,自动跳过标注缺失或格式错误的样本。 - **实现技巧**: - 在`dataset.yaml`中指定数据路径时,确保标注文件与图像一一对应。 - 使用`ultralytics`内置的`verify_image_label()`函数自动检测无效标注并生成错误日志[^2]。 ```python from ultralytics.yolo.data.utils import verify_image_label # 自定义数据加载时验证标注 def load_data(image_path): label_path = image_path.replace("images", "labels").replace(".jpg", ".txt") if not os.path.exists(label_path): print(f"跳过缺失标注的图像:{image_path}") return None return verify_image_label(image_path, label_path) # 自动验证标注完整性 ``` --- ### 2. **数据插补与合成** - **原理**:通过数据增强生成合理样本,补偿部分缺失数据。 - **实现技巧**: - 在`model.train()`中启用`augment=True`参数,自动应用默认增强(如翻转、裁剪)[^1]。 - 自定义增强策略(如Mosaic增强)以合成复杂场景: ```python model = YOLO("yolov8n.pt") model.train(data="coco128.yaml", epochs=100, augment=True, mosaic=0.5) # 50%概率启用Mosaic增强 ``` --- ### 3. **损失函数鲁棒性优化** - **原理**:通过调整损失函数权重,降低缺失标注对训练的影响。 - **实现技巧**: - 修改`default.yaml`中的分类/回归损失权重: ```yaml loss: cls: 0.5 # 分类损失权重 box: 0.05 # 回归损失权重 dfl: 0.5 # 分布损失权重 ``` - 使用Focal Loss缓解类别不平衡问题[^1]。 --- ### 4. **模型推理阶段的容错处理** - **原理**:在预测时自动过滤低置信度检测结果,避免缺失值干扰。 - **实现技巧**: ```python results = model.predict("input.jpg", conf=0.25, iou=0.7) # 设置置信度阈值和NMS参数 results.show() # 仅显示置信度>0.25的预测框 ``` ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值