数据预处理
admin
2024-02-10 00:42:32
0

数据预处理

通过准备和转换对数据集进行预处理,以用于训练。

Intuition

数据预处理可以分为两类过程:准备转换。将探索常见的预处理技术,然后针对特定应用逐步完成相关过程。

warning

某些预处理步骤global(不依赖于数据集,例如小写文本、删除停用词等)和其他步骤local(结构仅从训练拆分中学习,例如词汇、标准化等)。对于本地的、依赖于数据集的预处理步骤,要确保在预处理之前先拆分数据以避免数据泄漏。

准备中

准备数据涉及组织和清理数据。

加入

与现有数据表执行 SQL 连接,将您需要的所有相关数据组织到一个视图中。这使得使用数据集变得更加容易。

SELECT * FROM A
INNER JOIN B on A.id == B.id

warning

需要小心执行时间点有效连接以避免数据泄漏。例如,如果表 B 可能具有表 A 中的对象的特征,而这些特征在当时需要进行推理时不可用。

缺失值

首先,必须确定具有缺失值的行,一旦确定,有几种方法可以处理它们。

异常值(异常)

  • 关于什么是“正常”预期值的工艺假设

    # Ex. Feature value must be within 2 standard deviations
    df[np.abs(df.A - df.A.mean()) <= (2 * df.A.std())]

  • 注意不要删除重要的异常值(例如欺诈)

  • 当应用转换(例如幂律)时,值可能不是异常值

  • 异常可以是全局的(点)、上下文的(有条件的)或集体的(个体点不异常,集体是异常值)

特征工程

特征工程涉及以独特的方式组合特征以提取信号。

# Input
df.C = df.A + df.B

tips

特征工程可以与领域专家合作完成,领域专家可以指导设计和使用哪些特征。

cleaning

清理数据涉及应用约束,使模型更容易从数据中提取信号。

  • 使用领域专业知识和 EDA

  • 通过过滤器应用约束

  • 确保数据类型一致性

  • 删除具有特定列值或空列值的数据点

  • 图像(裁剪、调整大小、剪辑等)

    # Resize
    import cv2
    dims = (height, width)
    resized_img = cv2.resize(src=img, dsize=dims, interpolation=cv2.INTER_LINEAR)

  • 文本(下部、词干、词形还原、正则表达式等)

    # Lower case the text
    text = text.lower()

转换

转换数据涉及特征编码和工程。

缩放

  • 输入规模影响过程的模型需要

  • 从训练拆分中学习构造并应用于其他拆分(本地)

  • 不要盲目地缩放特征(例如分类特征)

  • 标准化:将值重新调整为均值为 0,标准为 1

    # Standardization
    import numpy as np
    x = np.random.random(4) # values between 0 and 1
    print ("x:\n", x)
    print (f"mean: {np.mean(x):.2f}, std: {np.std(x):.2f}")
    x_standardized = (x - np.mean(x)) / np.std(x)
    print ("x_standardized:\n", x_standardized)
    print (f"mean: {np.mean(x_standardized):.2f}, std: {np.std(x_standardized):.2f}")

    x: [0.36769939 0.82302265 0.9891467 0.56200803] mean: 0.69, std: 0.24 x_standardized: [-1.33285946 0.57695671 1.27375049 -0.51784775] mean: 0.00, std: 1.00

  • min-max:在最小值和最大值之间重新调整值

    # Min-max
    import numpy as np
    x = np.random.random(4) # values between 0 and 1
    print ("x:", x)
    print (f"min: {x.min():.2f}, max: {x.max():.2f}")
    x_scaled = (x - x.min()) / (x.max() - x.min())
    print ("x_scaled:", x_scaled)
    print (f"min: {x_scaled.min():.2f}, max: {x_scaled.max():.2f}")

    x: [0.20195674 0.99108855 0.73005081 0.02540603] min: 0.03, max: 0.99 x_scaled: [0.18282479 1. 0.72968575 0. ] min: 0.00, max: 1.00

  • 分箱:使用分箱将连续特征转换为分类特征

    # Binning
    import numpy as np
    x = np.random.random(4) # values between 0 and 1
    print ("x:", x)
    bins = np.linspace(0, 1, 5) # bins between 0 and 1
    print ("bins:", bins)
    binned = np.digitize(x, bins)
    print ("binned:", binned)

    x: [0.54906364 0.1051404 0.2737904 0.2926313 ] bins: [0. 0.25 0.5 0.75 1. ] binned: [3 1 2 2]

  • 还有更多!

编码

  • 允许有效地表示数据(保持信号)和有效地(学习模式,例如 one-hot 与嵌入)

  • label:分类值的唯一索引

    # Label encoding
    label_encoder.class_to_index = {
    "attention": 0,
    "autoencoders": 1,
    "convolutional-neural-networks": 2,
    "data-augmentation": 3,
    ... }
    label_encoder.transform(["attention", "data-augmentation"])

    array([2, 2, 1])

  • one-hot:表示为二进制向量

    # One-hot encoding
    one_hot_encoder.transform(["attention", "data-augmentation"])

    array([1, 0, 0, 1, 0, ..., 0])

  • 嵌入:能够表示上下文的密集表示

    # Embeddings
    self.embeddings = nn.Embedding(
        embedding_dim=embedding_dim, num_embeddings=vocab_size)
    x_in = self.embeddings(x_in)
    print (x_in.shape)

    (len(X), embedding_dim)

  • 还有更多!

Extraction

  • 从现有特征中提取信号

  • 结合现有功能

  • 迁移学习:使用预训练模型作为特征提取器并对其结果进行微调

  • 自动编码器:学习编码压缩知识表示的输入

  • 主成分分析(PCA):在较低维空间中对项目数据进行线性降维。

    # PCA
    import numpy as np
    from sklearn.decomposition import PCA
    X = np.array([[-1, -1, 3], [-2, -1, 2], [-3, -2, 1]])
    pca = PCA(n_components=2)
    pca.fit(X)
    print (pca.transform(X))
    print (pca.explained_variance_ratio_)
    print (pca.singular_values_)

    [[-1.44245791 -0.1744313] [-0.1148688 0.31291575] [ 1.55732672 -0.13848446]] [0.96838847 0.03161153] [2.12582835 0.38408396]

  • counts (ngram):文本的稀疏表示作为标记计数矩阵——如果特征值有很多有意义的、可分离的信号,则很有用。

    # Counts (ngram)
    from sklearn.feature_extraction.text import CountVectorizer
    y = [
        "acetyl acetone",
        "acetyl chloride",
        "chloride hydroxide",
    ]
    vectorizer = CountVectorizer()
    y = vectorizer.fit_transform(y)
    print (vectorizer.get_feature_names())
    print (y.toarray())
    # 💡 Repeat above with char-level ngram vectorizer
    # vectorizer = CountVectorizer(analyzer='char', ngram_range=(1, 3)) # uni, bi and trigrams

    ['acetone', 'acetyl', 'chloride', 'hydroxide'] [[1 1 0 0] [0 1 1 0] [0 0 1 1]]

  • similarity:类似于计数向量化,但基于标记的相似性

  • 还有更多!

随着时间的推移,通常会检索实体(用户、项目等)的特征值,并在不同项目中重用相同的特征。为确保检索到正确的特征值并避免重复工作,可以使用特征存储。

维度的诅咒

如果一个特征有很多唯一值但每个唯一值都有足够的数据点(例如 URL 作为特征),该怎么办?

显示答案

可以使用散列或使用它的属性而不是确切的实体本身来对数据进行编码。例如,通过用户的位置和收藏夹来表示用户而不是使用他们的用户 ID,或者使用其域而不是确切的 url 来表示网页。这种方法有效地减少了独特特征值的总数并增加了每个特征值的数据点数量。

应用

对于应用程序,将实施一些与数据集相关的预处理步骤。

特征工程

可以结合现有的输入特征来创建新的有意义的信号(帮助模型学习)。但是,如果不对不同的组合进行经验性试验,通常没有简单的方法可以知道某些特征组合是否有帮助。在这里,可以将项目的标题和描述分别用作特征,但会将它们组合起来创建一个输入特征。

# Input
df["text"] = df.title + " " + df.description

clean

由于正在处理文本数据,因此可以应用一些常见的文本预处理步骤:

!pip install nltk==3.7 -q

import nltk
from nltk.corpus import stopwords
from nltk.stem import PorterStemmer
import re

nltk.download("stopwords")
STOPWORDS = stopwords.words("english")
stemmer = PorterStemmer()

def clean_text(text, lower=True, stem=False, stopwords=STOPWORDS):
    """Clean raw text."""
    # Lower
    if lower:
        text = text.lower()

    # Remove stopwords
    if len(stopwords):
        pattern = re.compile(r'\b(' + r"|".join(stopwords) + r")\b\s*")
        text = pattern.sub('', text)

    # Spacing and filters
    text = re.sub(
        r"([!\"'#$%&()*\+,-./:;<=>?@\\\[\]^_`{|}~])", r" \1 ", text
    )  # add spacing between objects to be filtered
    text = re.sub("[^A-Za-z0-9]+", " ", text)  # remove non alphanumeric chars
    text = re.sub(" +", " ", text)  # remove multiple spaces
    text = text.strip()  # strip white space at the ends

    # Remove links
    text = re.sub(r"http\S+", "", text)

    # Stemming
    if stem:
        text = " ".join([stemmer.stem(word, to_lowercase=lower) for word in text.split(" ")])

    return text

# Apply to dataframe
original_df = df.copy()
df.text = df.text.apply(clean_text, lower=True, stem=False)
print (f"{original_df.text.values[0]}\n{df.text.values[0]}")

YOLO 和 RCNN 在真实世界视频上的比较将理论带入实验很酷。可以轻松地在 Colab 中训练模型,并在几分钟内找到结果。 比较 yolo rcnn 真实世界视频带来理论实验很酷很容易训练模型 colab 找到结果分钟

warning

将希望在它们变得更频繁时引入频率较低的特征,或者以巧妙的方式对它们进行编码(例如分箱、提取一般属性、常见的 n-gram、使用其他特征值进行平均编码等),以便可以减轻特征值维度问题,直到能够收集更多数据。

更换标签

根据EDA的发现,将应用几个约束来标记数据:

  • 如果数据点有目前不支持的标签,将用other
  • 如果某个标签没有足够的样本,会将其替换为other
import json
# Accepted tags (external constraint)
ACCEPTED_TAGS = ["natural-language-processing", "computer-vision", "mlops", "graph-learning"]# Out of scope (OOS) tags
oos_tags = [item for item in df.tag.unique() if item not in ACCEPTED_TAGS]
oos_tags


# Samples with OOS tags
oos_indices = df[df.tag.isin(oos_tags)].index
df[df.tag.isin(oos_tags)].head()

ID创建于标题描述标签
3个152020-02-28 23:55:26很棒的蒙特卡洛树搜索蒙特卡洛树搜索论文的精选列表......强化学习
371212020-03-24 04:56:38TensorFlow2 中的深度强化学习deep-rl-tf2 是一个实现...强化学习
672182020-04-06 11:29:57使用 TensorFlow2 的分布式强化学习🐳 各种分布式资源的实现...强化学习
742392020-04-06 18:39:48Prophet:大规模预测为...生成高质量预测的工具时间序列
952772020-04-07 00:30:33强化学习课程课程学习应用于强化学习...强化学习
# Replace this tag with "other"
df.tag = df.tag.apply(lambda x: "other" if x in oos_tags else x)
df.iloc[oos_indices].head()

ID创建于标题描述标签
3个152020-02-28 23:55:26很棒的蒙特卡洛树搜索蒙特卡洛树搜索论文的精选列表......其他
371212020-03-24 04:56:38TensorFlow2 中的深度强化学习deep-rl-tf2 是一个实现...其他
672182020-04-06 11:29:57使用 TensorFlow2 的分布式强化学习🐳 各种分布式资源的实现...其他
742392020-04-06 18:39:48Prophet:大规模预测为...生成高质量预测的工具其他
952772020-04-07 00:30:33强化学习课程课程学习应用于强化学习...其他

还将限制映射到仅高于特定频率阈值的标签。没有足够项目的标签将没有足够的样本来建模它们的关系。

# Minimum frequency required for a tag
min_freq = 75
tags = Counter(df.tag.values)

# Tags that just made / missed the cut
@widgets.interact(min_freq=(0, tags.most_common()[0][1]))
def separate_tags_by_freq(min_freq=min_freq):
    tags_above_freq = Counter(tag for tag in tags.elements()
                                    if tags[tag] >= min_freq)
    tags_below_freq = Counter(tag for tag in tags.elements()
                                    if tags[tag] < min_freq)
    print ("Most popular tags:\n", tags_above_freq.most_common(3))
    print ("\nTags that just made the cut:\n", tags_above_freq.most_common()[-3:])
    print ("\nTags that just missed the cut:\n", tags_below_freq.most_common(3))
)))

Most popular tags: [('natural-language-processing', 388), ('computer-vision', 356), ('other', 87)] Tags that just made the cut: [('computer-vision', 356), ('other', 87), ('mlops', 79)] Tags that just missed the cut: [('graph-learning', 45)]

def filter(tag, include=[]):
    """Determine if a given tag is to be included."""
    if tag not in include:
        tag = None
    return tag

# Filter tags that have fewer than  occurrences
tags_above_freq = Counter(tag for tag in tags.elements()
                          if (tags[tag] >= min_freq))
df.tag = df.tag.apply(filter, include=list(tags_above_freq.keys()))

# Fill None with other
df.tag = df.tag.fillna("other")

编码

将对输出标签进行编码,将为每个标签分配一个唯一索引。

import numpy as np
import random

# Get data
X = df.text.to_numpy()
y = df.tag

将编写自己的基于 scikit-learn实现的 LabelEncoder 。能够为想要创建的对象编写干净的类是一项非常有价值的技能。

class LabelEncoder(object):
    """Encode labels into unique indices"""
    def __init__(self, class_to_index={}):
        self.class_to_index = class_to_index or {}  # mutable defaults ;)
        self.index_to_class = {v: k for k, v in self.class_to_index.items()}
        self.classes = list(self.class_to_index.keys())

    def __len__(self):
        return len(self.class_to_index)

    def __str__(self):
        return f""

    def fit(self, y):
        classes = np.unique(y)
        for i, class_ in enumerate(classes):
            self.class_to_index[class_] = i
        self.index_to_class = {v: k for k, v in self.class_to_index.items()}
        self.classes = list(self.class_to_index.keys())
        return self

    def encode(self, y):
        encoded = np.zeros((len(y)), dtype=int)
        for i, item in enumerate(y):
            encoded[i] = self.class_to_index[item]
        return encoded

    def decode(self, y):
        classes = []
        for i, item in enumerate(y):
            classes.append(self.index_to_class[item])
        return classes

    def save(self, fp):
        with open(fp, "w") as fp:
            contents = {"class_to_index": self.class_to_index}
            json.dump(contents, fp, indent=4, sort_keys=False)

    @classmethod
    def load(cls, fp):
        with open(fp, "r") as fp:
            kwargs = json.load(fp=fp)
        return cls(**kwargs)

如果您不熟悉装饰器,请从Python 课程@classmethod中了解更多信息。

# Encode
label_encoder = LabelEncoder()
label_encoder.fit(y)
num_classes = len(label_encoder)

label_encoder.class_to_index

{'computer-vision': 0, 'mlops': 1, 'natural-language-processing': 2, 'other': 3}

label_encoder.index_to_class

{0: 'computer-vision', 1: 'mlops', 2: 'natural-language-processing', 3: 'other'}

# Encode
label_encoder.encode(["computer-vision", "mlops", "mlops"])

array([0, 1, 1])

# Decode
label_encoder.decode(np.array([0, 1, 1]))

['computer-vision', 'mlops', 'mlops']


要对输入文本特征进行的许多转换都是特定于模型的。例如,对于简单的基线,可以做label encodingtf-idf而对于更复杂的架构,可以做label encoding→ one-hot encoding→ embeddings。因此,在实施基线时,将在下一组课程中介绍这些内容。

在下一节中,将对预处理后的数据集执行探索性数据分析 (EDA)。但是,步骤的顺序可以颠倒,具体取决于问题的定义程度。如果不确定如何准备数据,可以使用 EDA 来弄清楚,反之亦然。

本文主体源自以下链接:

@article{madewithml,
    author       = {Goku Mohandas},
    title        = { Made With ML },
    howpublished = {\url{https://madewithml.com/}},
    year         = {2022}
}

本文由 mdnice 多平台发布

相关内容

热门资讯

linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
C++ 机房预约系统(六):学... 8、 学生模块 8.1 学生子菜单、登录和注销 实现步骤: 在Student.cpp的...
A.机器学习入门算法(三):基... 机器学习算法(三):K近邻(k-nearest neigh...
数字温湿度传感器DHT11模块... 模块实例https://blog.csdn.net/qq_38393591/article/deta...
有限元三角形单元的等效节点力 文章目录前言一、重新复习一下有限元三角形单元的理论1、三角形单元的形函数(Nÿ...
Redis 所有支持的数据结构... Redis 是一种开源的基于键值对存储的 NoSQL 数据库,支持多种数据结构。以下是...
win下pytorch安装—c... 安装目录一、cuda安装1.1、cuda版本选择1.2、下载安装二、cudnn安装三、pytorch...
MySQL基础-多表查询 文章目录MySQL基础-多表查询一、案例及引入1、基础概念2、笛卡尔积的理解二、多表查询的分类1、等...
keil调试专题篇 调试的前提是需要连接调试器比如STLINK。 然后点击菜单或者快捷图标均可进入调试模式。 如果前面...
MATLAB | 全网最详细网... 一篇超超超长,超超超全面网络图绘制教程,本篇基本能讲清楚所有绘制要点&#...
IHome主页 - 让你的浏览... 随着互联网的发展,人们越来越离不开浏览器了。每天上班、学习、娱乐,浏览器...
TCP 协议 一、TCP 协议概念 TCP即传输控制协议(Transmission Control ...
营业执照的经营范围有哪些 营业执照的经营范围有哪些 经营范围是指企业可以从事的生产经营与服务项目,是进行公司注册...
C++ 可变体(variant... 一、可变体(variant) 基础用法 Union的问题: 无法知道当前使用的类型是什...
血压计语音芯片,电子医疗设备声... 语音电子血压计是带有语音提示功能的电子血压计,测量前至测量结果全程语音播报࿰...
MySQL OCP888题解0... 文章目录1、原题1.1、英文原题1.2、答案2、题目解析2.1、题干解析2.2、选项解析3、知识点3...
【2023-Pytorch-检... (肆十二想说的一些话)Yolo这个系列我们已经更新了大概一年的时间,现在基本的流程也走走通了,包含数...
实战项目:保险行业用户分类 这里写目录标题1、项目介绍1.1 行业背景1.2 数据介绍2、代码实现导入数据探索数据处理列标签名异...
记录--我在前端干工地(thr... 这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 前段时间接触了Th...
43 openEuler搭建A... 文章目录43 openEuler搭建Apache服务器-配置文件说明和管理模块43.1 配置文件说明...