构建高质量机器学习数据集的初学者指南

2023年11月17日 由 alex 发表 448 0

在本文中,我们将通过一个简单的案例,利用以数据为中心的人工智能范式来实现高质量的数据,并提高我们的机器学习分类结果。


遵循以数据为中心的人工智能的口号 —— 一切都关乎数据 —— 我们在任何时候都不会深入模型本身。


我们将使用 Pima Indians Diabetes Dataset(。你还可以在以数据为中心的人工智能社区 GitHub 找到所有的代码和额外材料。


第一步:执行数据概览以了解数据


在我们开始整理数据集之前,我们需要了解我们试图解决的问题以及我们正在处理的数据的特点。彻底了解我们的数据特性、问题的复杂性和使用案例领域,是以数据为中心的人工智能的首要原则之一。


这将帮助我们确定在机器学习流程中下一步应该采取的步骤。


当涉及到数据概览时,有几个有趣的开源工具可供探索:我自己对几个工具做了评测,包括 ydata-profiling、dataprep、sweetviz、autoviz 和 lux。


我目前主要使用 ydata-profiling:我觉得它是一个顶级工具,适用于数据从业者,它不是让我们跳过 pandas 的环节来最大程度地了解我们数据的特性和可视化,而是让我们在几行代码中就能完成所有这些。


首先,你需要安装 ydata-profiling:


pip install ydata-profiling==4.6.1


然后,我们可以通过保存一个.html报告来获取数据的完整概览,报告中包含了所有我们开始需要的特征和可视化信息。


import pandas as pd
from ydata_profiling import ProfileReport
df = pd.read_csv('diabetes.csv')
# Generate the report
profile = ProfileReport(df,title="Diabetes Data Profile")
# Save the report to .html
profile.to_file("diabetes_report.html")


数据报告让我们立即了解我们数据的总体特征,并突出显示了一些我们可能需要考虑的警告。


屏幕截图2023-11-17132658


这个数据集包含768个观察值和9个变量/特征。其中8个是数值型,1个被识别为分类变量(结果看起来是我们的目标变量)。没有重复行,而且显然没有缺失值。最后,一些特征之间发现有高度相关性的警告。此外,几个特征有大量的零值。


查看一些突出显示的特征(例如,BMI),我们可以看到这些值与整体分布相距甚远。借助领域知识,这些“0”值实际上是无意义的:0 值是可以的,Pregnancies但对于 BMI、血糖、胰岛素、血压或皮肤厚度来说是无效的。


3


我们很快就意识到这些零代表了什么:缺失的数据。


目前我们会着手解决这个问题,但通过彻底的探索性数据分析(EDA)可以理解得更多。


第二步:调查数据质量问题


既然我们发现有些列包含无效的零值,我们就可以开始处理数据集上的缺失数据问题。


许多机器学习模型和scikit-learn估计器天生不支持缺失值,因此在将数据集输入估计器之前,我们需要以某种方式处理这些NaN值。


首先,让我们将这些0值标记为NaN值:


import numpy as np
df[['Glucose', 'BloodPressure', 'SkinThickness', 'Insulin', 'BMI']] = df[['Glucose', 'BloodPressure', 'SkinThickness', 'Insulin', 'BMI']].replace(0, np.nan)


现在,我们可以使用数据填补技术来替换NaN观测值,用看似合理的替代值来代替。


目前我们将使用一种非常简单的方法——SimpleImputer——来替换零值,用每个特征的平均值来代替。这是一种非常天真的方法,很可能会在我们的分布中造成一些不希望的“峰值”,但目标仅仅是为了展示如何突出显示和填补缺失数据,我们之后可以尝试更好的方法。


from sklearn.model_selection import train_test_split
from sklearn.impute import SimpleImputer
# Split data into training and test
X = df.iloc[:,:-1]
y = df.iloc[:,-1]
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
# Perform data imputation
imputer = SimpleImputer(strategy='mean')
imputer.fit(X_train)
X_train = imputer.transform(X_train)
X_train = pd.DataFrame(X_train, columns=df.columns[:-1])
X_test = imputer.transform(X_test)
X_test = pd.DataFrame(X_test, columns=df.columns[:-1])
# Keep integer values in selected columns
X_train[['Glucose', 'BloodPressure', 'SkinThickness', 'Insulin', 'BMI']] = X_train[['Glucose', 'BloodPressure', 'SkinThickness', 'Insulin', 'BMI']].round(0)
X_test[['Glucose', 'BloodPressure', 'SkinThickness', 'Insulin', 'BMI']] = X_test[['Glucose', 'BloodPressure', 'SkinThickness', 'Insulin', 'BMI']].round(0)


现在,我们可以尝试一个非常简单的决策树分类器,并查看我们分类结果的基线会是怎样。说明一下,决策树可以通过代理分割或其他方法自然地扩展以支持缺失值。的确,在 scikit-learn 的文档中看起来像是决策树在某些条件下对缺失值有内置支持,当前版本(1.3.2)。然而,当我使用版本 1.2.2 时,我遇到了这个错误:


4


即便是NaN值在内部处理了,用缺失数据训练模型也不是一个好做法,因为这会危及模型从杂乱和有限的信息中学到的概念。


from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score, classification_report
from sklearn.metrics import confusion_matrix
clf = DecisionTreeClassifier()
clf.fit(X_train, y_train)
y_pred = clf.predict(X_test)
report = classification_report(y_test, y_pred)
print("Classification Report:\n", report)
conf_matrix = confusion_matrix(y_test, y_pred)
print(conf_matrix)

这是混淆矩阵:
array([[73, 26],
       [26, 29]])


1_t6fEc_W-V5QurNG9rwieVg


这是混淆矩阵:


array([[73, 26],
       [26, 29]])


第三步:扩大代表性不足的类别


如果我们在第一步中有所注意,我们的目标类别,结果,是不平衡的。或许没有到触发默认设置中的警告的地步(默认阈值是0.5),但足以让分类器偏向多数类别,忽视少数类别。这一点从分析报告中呈现的数据可视化中就很明显:


6


请注意,尽管数据缺失可能是由数据收集、传输或存储过程中的多个错误引起的,但是类别不平衡可能反映了领域的自然特性:例如,这家医疗中心被诊断为糖尿病的患者本来就少。


尽管如此,为了保证模型不会忽视少数情况,采取措施处理训练数据仍然很重要:实际上,这正是我们试图更准确预测的内容。


假阳性是不好的,因为它会给健康的患者错误的信息,告诉她患有糖尿病。但是当进行了额外的测试时,这仅仅是一个“惊吓”。


然而,在这种情况下,漏报更糟糕。我们会告诉一位糖尿病患者一切都好,她没有被诊断出病情,疾病就会进展。


增加这些数字的一种方法是使用数据过采样技术。数据过采样是数据从业者中一种流行的技术,用于调整数据集的分布——即,数据中现有类别或类别之间的比例——从而缓解数据不平衡的问题。


并且这只是合成数据众多有趣且有用的应用之一。


虽然合成数据可以有多种解释——例如,“假数据”、“虚拟数据”、“模拟数据”——但在这里,我们指的是“数据驱动”的合成数据生成。


在这个意义上,合成数据是人为生成的,保留了真实数据的特征——其结构、统计特性、依赖关系和相关性。


为了快速理解合成数据如何用于增强,我们将利用 ydata-synthetic 包,并尝试他们的高斯混合模型。


首先,我们需要安装该包:


pip install ydata-synthetic==1.3.1


完成这部分之后,创建合成数据变得非常直接了。


from ydata_synthetic.synthesizers.regular import RegularSynthesizer
from ydata_synthetic.synthesizers import ModelParameters, TrainParameters

X_train.reset_index(drop=True, inplace=True)
y_train = pd.DataFrame(y_train, columns=[df.columns[-1]])
y_train.reset_index(drop=True, inplace=True)
train_df = pd.concat([X_train, y_train], axis=1)
num_cols = list(df.columns[:-1])
cat_cols = [df.columns[-1]] 
synth = RegularSynthesizer(modelname='fast')
synth.fit(data=train_df, num_cols=num_cols, cat_cols=cat_cols)
# Generate 1000 samples
synth_data = synth.sample(1000)
# Keep newly generated values aligned with the range and format of original features
synth_data[['Pregnancies', 'Glucose', 'BloodPressure', 'SkinThickness', 'Insulin', 'BMI', 'Age']] = synth_data[['Pregnancies', 'Glucose', 'BloodPressure', 'SkinThickness', 'Insulin', 'BMI', 'Age']].applymap(lambda x: max(round(x, 0), 0))
synth_data[['DiabetesPedigreeFunction']] = synth_data[['DiabetesPedigreeFunction']].applymap(lambda x: max(x, 0))


在我们拥有了合成数据之后,我们可以简单地从合成数据中抽取一部分新生成的少数类样本的子集,并将其添加到训练数据中,以创建一个平衡的(即50%-50%)分布:


min_df = synth_data[synth_data['Outcome']==1]
min_df.reset_index(drop=True, inplace=True)
min_sample_df = min_df.sample(188).reset_index(drop=True)
synth_df = pd.concat([train_df, min_sample_df], axis=0)


我们来看看这将如何影响我们决策树的学习及其随后的结果:


clf = DecisionTreeClassifier()
X_aug = synth_df.iloc[:, :-1]
y_aug = synth_df.iloc[:,-1]
clf.fit(X_aug, y_aug)
y_pred = clf.predict(X_test)
# Classification results
report = classification_report(y_test, y_pred)
print("Classification Report:\n", report)
conf_matrix = confusion_matrix(y_test, y_pred)
print(conf_matrix)


7


以及混淆矩阵:


array([[67, 32],
       [15, 40]])


请注意,我们如何通过对训练集进行简单的修改,使得我们的F得分性能提升了10%,并显著改善了小众类别的敏感性结果(从53%提高到73%)。


数据中心人工智能范式的美在于此:我们没有触碰我们的模型参数,仅仅通过非常简单的启发式方法和标准技术,显著提高了我们训练集的质量 。


总结


在本文中,我们通过一个非常实践的用例,体验了数据中心人工智能范式。


我们从理解我们的数据开始,常规操作。我们发现、调查并解决了数据质量问题,如缺失数据,并通过合成数据改进我们的训练数据,以克服这一领域的不平衡性。当然,对于这样一个快速且简单的案例研究,我们专注于使用简单的启发式方法来完成任务,但数据科学家的工作永远不会停止。




文章来源:https://towardsdatascience.com/a-beginners-guide-to-building-high-quality-datasets-for-machine-learning-586a2ce7a565
欢迎关注ATYUN官方公众号
商务合作及内容投稿请联系邮箱:bd@atyun.com
评论 登录
热门职位
Maluuba
20000~40000/月
Cisco
25000~30000/月 深圳市
PilotAILabs
30000~60000/年 深圳市
写评论取消
回复取消