SciFiPi - 清理机器学习数据集的科学过滤管道
项目描述
科幻小说
清理机器学习数据集的科学过滤管道
用法
SciFiPi 可以用作带有命令行界面 (CLI) 的独立工具,也可以用作可以包含到自己代码中的库。这两个选项描述如下
命令行界面
为了将 SciFiPi 用作 CLI 工具,首先克隆此存储库或下载代码。获取代码后,在 src 文件夹中打开一个 shell 并python SciFiPi.py --filters "filter1 | filter2("arg1", "arg2") | filterN" 使用 filter1 - filterN 作为您要应用的预过滤器和过滤器执行。请注意,它们不必按任何特定顺序排列。您甚至可以混合使用预过滤器和过滤器,SciFiPi 会处理好顺序。过滤器由竖线字符分隔。如果将任何参数传递给滞后或噪声过滤器,它们将在括号中传递,例如 lag([[1, 2],[4, 5]]) 以消除第 1/2 和 3/4 列中的滞后或噪声( [2]) 过滤第二列中的噪声。请注意,您必须将脏数据(一个或多个 csv 文件)放入dirty_data目录中。
图书馆
为了在您自己的项目中使用 SciFiPi,只需通过pip install SciFiPi. 然后,您可以通过将一个或多个路径传递给 csv 文件来创建预过滤器对象。创建预过滤器后,应用任意数量的预过滤器。
from SciFiPi.PreFilterBuilder import PreFilterBuilder
from SciFiPi.FilterBuilder import FilterBuilder
preFilterBuilder = PreFilterBuilder("path1.csv", "path2.csv")
preFilteredDataFrame = preFilterBuilder.filterDuplicates().filterImputation().getDataFrame()
预过滤后,是时候应用真正的过滤器了。使用 实例化 filterBuilderpreFilteredDataFrame并应用您想要应用的过滤器。完成调用getDataFrame()以获取已清理的数据帧。
filterBuilder = FilterBuilder(preFilteredDataFrame)
cleanDataFrame = filterBuilder.filterNoise([[2,5], [1, 2]]).filterDecimalShift().getDataFrame()
建筑学
主意
SciFiPi 的想法是提供一个灵活的数据清理和过滤管道,涵盖各种用例。您可以以任意顺序应用各种过滤器,如果这还不够,SciFiPi 提供了一种扩展机制,允许使用自定义过滤器函数扩展库。
我们架构的主要原则是一种在面向对象编程中广泛使用的设计模式,一种流畅的接口。该接口允许任意链接过滤器,而用户不必担心方法调用的顺序。下面描述的所有过滤功能都由所谓的FilterBuilders提供,它们实现了流畅的接口模式。
SciFiPi 现有的过滤器可以分为三类:
- 清洁器和准备器:我们将第一类过滤器称为清洁器或准备器,因为它们负责数据集的初始准备(即加载和清洁)。此类别包含从文件夹中读取单个文件或多个文件的功能。此外,第一类的这个函数负责正确的索引(即通过时间戳)并确保数据集的内容都是“数字”类型的。如果数据集条目无法转换为数字,则会在此处标记为“NaN”。在这一步中,没有应用先进的填充技术。
- PreFilters:第二类,即所谓的PreFilters ,包含用于简单过滤操作的功能。此类别中的过滤器负责处理重复的列,确保数据集是等距的并填充上一步中的“NaN”。
- 过滤器:第三类包含一些更高级的过滤功能,例如噪声过滤器、滞后过滤器以及由单位偏移引起的值偏移。
清洁剂和准备剂清单
这些过滤器默认运行:
formatData()(“Cleaner” - 默认运行):这实际上不是其他过滤器。在 PreFilterBuilder 的构造函数中调用 FormatData 将读取的数据格式化为标准格式,供后面的实际过滤器使用。因此合并了多个文件,所有文件都转换为矩阵格式,非数据行作为信号名称和单位被删除,然后设置为列名。此外,时间戳被设置为索引,所有单元格都被转换为数字。
预过滤器列表
filterDuplicates()(CLI:“duplicates”): DuplicatesFilter 检查每个可能的列对是否完全匹配(简单方法)。或者,可以使用更高级的方法,其中列对的相似性是使用 sklearn 和 scipy 库的余弦相似度和欧几里德距离来计算的。两种相似性度量的组合检查导致精确、线性变换和部分重复。filterEquidistance()(CLI: "equidistance"): EquidistanceFilter 使用模式查找索引列中出现频率最高的距离值。然后使用 pandas 库中的 resample() 方法重新创建索引,并将偏移量设置为最频繁的距离值。filterImputation()(CLI:“插补”):添加缺失值。在小数据帧(少于三列)上,缺失值通过回填替换。在较大的数据帧上,缺失值是通过决策树添加的,回填作为后备策略。filterFillTimestamps()(CLI:“fillTimestamps”):fillTimestamps-Filter 正在扫描数据帧索引以查找 NaT。如果找到 NaT,则由开始时间和时间戳之间的差异创建合成时间戳。然后索引由这个合成时间戳填充。filterFixTimezone()(CLI:“fixtimezone”):FixTimezoneFilter 正在数据帧索引中搜索时区信息。如果找到时区信息,则将其转换为日期时间格式。如果没有给出时区信息,则设置本地时区。通过将时区信息添加到数据帧的索引中,各个数据帧的信号按记录的时间映射。
过滤器列表
您可以按任意顺序使用任意数量的以下过滤器:
filterDecimalShift()(CLI:“decimalshift”):检查由小数位错误引起的数据突然跳跃。然后将识别出的错误乘以/除以 10。filterNoise([col1, col2])(CLI:“noise([col1, col2])”):NoiseFilter 使用 k-Nearest-Neighbours 回归器(来自 sklearn 库)来自我预测列并去除噪声。参数(此处为“col1,col2”)定义要从中去除噪声的列。filterLag([[col1, col2], [col3, col4]])(CLI:“lag([[col1, col2], [col3, col4]])"):LagFilter 使用动态时间规整(DTW - 来自 dtwalign 库)动态对齐两个滞后列并在各自的数据帧中重新创建它们列。这些参数定义了考虑滞后修复的列对。
扩展 SciFiPi
我们刚刚启动 SciFiPi 作为对KEEN 黑客松的提交,并实现了一组基本的过滤器。我们知道这只是第一步,对你们中的一些人来说可能还不够。在这种情况下,您可以通过编写自己的PreFilters或Filters来简单地扩展 SciFiPi 。为此,您必须执行以下两个步骤:
- 编写您的自定义过滤器类。您应该遵守命名约定:您的类的名称应该是 (FilterFunction) + Filter。
- 在PreFilterBuilder(用于自定义 PreFilters)或FilterBuilder(用于自定义 Filters)中注册它。
以下代码段显示了第 1 步,编写自定义过滤器:
from filters.Filter import Filter
# Create your own filter class and extend the base filter
class CustomFilter(Filter):
# Override the "applyFilter" function
def applyFilter(self, dataFrame:pd.DataFrame):
# Do with the dataFrame whatever you want, but make sure to return the changed dataFrame it in the end
return dataFrame
如您所见,它非常简单。扩展基Filter类并覆盖 applyFilter 方法。
第二步,注册您的过滤器显示在下一个代码片段中:
class FilterBuilder:
# Existing filters ...
def filterCustom(self):
filter = CustomFilter()
self.dataFrame = filter.applyFilter(self.dataFrame)
return self
这也相当简单。为您的过滤器定义一个函数。为了让我们的 CLI 工作,它必须遵循命名方案“filter”+(FilterFunction)。在新函数内部,创建一个过滤器实例并applyFilter() 在返回 self 之前调用该函数。最后一行我们要求不要破坏流畅的界面。
当前限制
由于时间有限,仍然存在一些限制。
- 由于计算复杂度高,等距离滤波器的运行时间很长。
- DecimalShiftFilter 有时对变化很敏感。有时在没有小数移位的情况下会检测到小数移位。如果人为降低灵敏度,则不再检测到一些真正的小数移位。
- LagFilter 需要指定哪些列可以通过时间滞后链接。
- NoiseFilter 需要关于哪些列应该从噪声中释放出来的指令。这是由于列的个别特性 - 在一个传感器中构成噪声的因素可能是其他传感器的有效数据。