29、显式类别与字符串向量在数据处理中的应用

显式类别与字符串向量在数据处理中的应用

显式类别

在数据处理中,我们常常会遇到不同类型的变量,其中概念上存在着仅具有少量测量值的变量和真正的分类变量之间的差异。分类变量(因子变量)能让我们更准确地表达对其使用的意图,还能实现一些额外的API功能和性能优化。

示例分析

以一个房地产开发项目的数据为例,数据包含了地块编号(Lot #)、地址(Address)、面积(Acres)和房屋风格(House Style)等信息,如下表所示:
| Lot # | Address | Acres | House Style |
| — | — | — | — |
| 32849 | 111 Middle Rd | 2 | 37 |
| 34210 | 23 High St | 1 | 21 |
| 39712 | 550 Lowe Ave | 3 | 22 |
| 40015 | 230 Cross St | 1 | 21 |
| 32100 | 112 Middle Rd | 1 | 14 |
| 30441 | 114 Middle Rd | 2 | 22 |

我们可以根据一定的领域知识来判断每个特征的性质:
- 地块编号和地址 :地块编号通常是用来唯一描述一个房产的,地址也有类似的作用。虽然一个是整数类型,一个是字符串类型,但重要的是它们的值代表了每个记录的独特信息。即使偶尔会有地块细分或未开发无地址的情况,但总体上这些值具有近似的独特性,因此它们不是合适的分类变量候选。
- 房屋风格 :房屋风格可能是从开发商提供的相对较少的标准户型中选择的。它虽然被编码为整数,但也可以用简短的名称来表示相同的意图。考虑到未来可能会有定制户型的房屋,我们可以用“CUSTOM”这样的名称或 -1 这样的特殊数字来编码。因此,房屋风格很可能是一个分类变量。
- 面积 :如果仅看当前的数据,面积变量可能会误导我们。它是一个整数,且不同值的数量比房屋风格还少。但从领域知识可知,新开发项目通常会划分成固定的地块大小,但随着时间推移,地块可能会细分或合并,导致面积不再是整数或常见的值。所以,即使初始值可能暗示它是分类变量,但实际上我们不希望将其编码为分类变量,使用浮点数可能更合适。

使用Pandas处理分类变量

在处理包含人类姓名的数据集时,我们可以使用Pandas来读取数据,丢弃不常见的姓名,然后将姓名列转换为分类变量。以下是具体的操作步骤:
1. 读取数据

import pandas as pd
humans = pd.read_csv('data/humans-names.csv')
  1. 丢弃不常见的姓名
name_counts = humans.Name.value_counts()
uncommon = name_counts[name_counts < 10]
humans = (humans
          .set_index('Name')
          .drop(uncommon.index)
          .reset_index())
  1. 将姓名列转换为分类变量
humans['Name'] = humans.Name.astype('category')

转换后,虽然使用这个DataFrame的方式基本不变,但过滤操作会更快。例如,我们可以像处理字符串字段一样处理姓名列,但过滤速度会提升:

humans[humans.Name == 'Mary']
使用R的Tidyverse处理分类变量

在R的Tidyverse中,处理分类变量的方式与Pandas略有不同。以下是具体的操作步骤:
1. 读取数据

library(tidyverse)
humans <- read_csv('data/humans-names.csv')
  1. 将姓名列转换为因子变量
humans <- mutate_at(humans, vars(Name), factor)
  1. 将出现次数少于100次的姓名合并为“UNCOMMON”
library(forcats)
humans['Name'] <- fct_lump_min(humans$Name, min = 100, other_level = "UNCOMMON")

转换后,我们可以查看因子变量的级别:

levels(humans$Name)

还可以过滤出姓名为“UNCOMMON”的记录:

humans %>% filter(Name == "UNCOMMON")

最后,我们可以使用ggplot2绘制姓名分布的柱状图:

library(ggplot2)
ggplot(humans, aes(y = Name)) + geom_bar(stat = "count")
字符串向量

自然语言处理(NLP)是数据科学的一个重要子领域,我们关注的一个细分领域是如何将自然语言字符串编码为机器学习模型可以接受的数值特征。

词袋模型(Bag-of-words)

词袋模型是一种将自然语言文本转换为向量的简单方法。其基本思想是先为整个语料库构建一个词汇表,即包含语料库中所有单词的集合。然后,我们可以用一个长度等于词汇表大小的向量来表示语料库中的每个文本,向量的每个维度表示该单词的出现次数。

以下是使用词袋模型处理一首诗的示例代码:

import nltk
import re
import numpy as np

# 示例诗
second_coming = """
Turning and turning in the widening gyre   
The falcon cannot hear the falconer;
Things fall apart; the centre cannot hold;
Mere anarchy is loosed upon the world,
The blood-dimmed tide is loosed, and everywhere   
The ceremony of innocence is drowned;
The best lack all conviction, while the worst   
Are full of passionate intensity.
Surely some revelation is at hand;
Surely the Second Coming is at hand.   
The Second Coming! Hardly are those words out   
When a vast image out of Spiritus Mundi
Troubles my sight: somewhere in sands of the desert   
A shape with lion body and the head of a man,   
A gaze blank and pitiless as the sun,   
Is moving its slow thighs, while all about it   
Reel shadows of the indignant desert birds.   
The darkness drops again; but now I know   
That twenty centuries of stony sleep
Were vexed to nightmare by a rocking cradle,   
And what rough beast, its hour come round at last,   
Slouches towards Bethlehem to be born?
"""

# 简化文本
def simplify_text(text):
    stops = nltk.corpus.stopwords.words('english')
    words = re.findall(r'[a-z]+', text.lower())
    return [w for w in words if w not in stops]

poem = simplify_text(second_coming)

# 创建词汇表到向量索引的映射
word2ndx = {w: n for (n, w) in enumerate(set(poem))}
print(f"Vector dimensions={len(word2ndx)}")

# 生成词袋向量
def make_vector(words, word2ndx=word2ndx):
    vec = np.zeros(len(word2ndx), dtype=np.uint16)
    for word in words:
        assert word in word2ndx
        n = word2ndx[word]
        vec[n] += 1
    return vec

# 对每一节诗进行向量编码
for i, stanza in enumerate(second_coming.split('\n\n')):
    print(f"Stanza {i+1}:")
    print(make_vector(simplify_text(stanza)))

通过词袋模型,我们可以得到每一节诗的向量表示,这些向量反映了不同节诗之间的语义差异。

Word2Vec

Word2Vec是一种比词袋模型更强大的向量表示技术。它使用两层神经网络来考虑每个单词的上下文,从而生成具有语义意义的向量。例如,在一个大型英语语料库上训练后,我们可以通过向量的加减法来捕捉单词之间的语义关系。

Doc2Vec

基于Word2Vec的改进版本Doc2Vec,也称为段落向量。在Python的gensim库中,我们可以使用Doc2Vec来对文档进行标记,并生成向量表示。

以下是使用Doc2Vec处理航空公司推文数据集的示例代码:

import sqlite3
from pprint import pprint
from gensim.models.doc2vec import Doc2Vec, TaggedDocument

# 连接数据库并查询数据
db = sqlite3.connect('data/Airline-Tweets.sqlite')
cur = db.cursor()
sql = """
SELECT name, airline, text 
FROM Tweets
"""
cur.execute(sql)
tweets = cur.fetchall()

# 打印部分数据
pprint(tweets[5000:5003], width=60)

# 准备文档
docs = []
for (author, airline, msg) in tweets:
    td = TaggedDocument(simplify_text(msg), [author, airline])
    docs.append(td)

# 训练Doc2Vec模型
model = Doc2Vec(docs, vector_size=10, window=2, min_count=4)

# 查看词汇表大小
print("Number of words:", len(model.wv.vocab))

# 查看部分词汇
print(list(model.wv.vocab)[:7])

# 获取现有推文的向量表示
msg = tweets[11001][2]
print(msg)
print(model.infer_vector(simplify_text(msg)))

# 获取新消息的向量表示
badservice = model.infer_vector(['bad', 'service'])
print(badservice)

# 查找与“bad service”最相似的单词
print(model.wv.most_similar(['bad', 'service']))

# 获取航空公司的向量表示
airlines = ('Delta', 'United', 'JetBlue')
delta, united, jetblue = (model.docvecs[x] for x in airlines)
print(f"Delta:\n{delta}\n")
print(f"United:\n{united}\n")
print(f"JetBlue:\n{jetblue}\n")

通过Doc2Vec,我们可以将推文转换为向量表示,并使用余弦相似度等方法来比较不同向量之间的关系。

总结

在数据处理中,正确识别和处理分类变量可以提高数据的存储效率和处理性能。而在自然语言处理中,词袋模型、Word2Vec和Doc2Vec等技术可以将自然语言文本转换为数值特征,为机器学习模型提供输入。这些技术在不同的场景中都有各自的优势和适用范围,我们可以根据具体需求选择合适的方法。

显式类别与字符串向量在数据处理中的应用(续)

词法处理:词干提取与词形还原

在自然语言处理中,识别单词本身也是一个重要的方面。对于“相同”单词的屈折形式,通常最好将它们视为相同的基本形式。这可以通过词干提取(stemming)或词形还原(lemmatization)来实现。

  • 词干提取 :词干提取试图通过去除常见词缀来识别构成单词形态根的几个字母。例如,“seeking”、“seeks”等词经过词干提取后可能会得到相同的词干“seek”。
  • 词形还原 :词形还原则更进一步,它会利用语法上下文和音位关系。例如,一个词形还原器可能会将作为动词的“dove”规范为“dive”(即“跳跃”的意思),而将作为名词的“dove”保持为“dove”(即“鸽子”的意思)。

在前面使用的代码中, simplify_text 函数在一定程度上进行了类似词干提取和词形还原的操作,通过去除停用词和规范化大小写,将文本转换为更简单的形式。

向量比较与应用

Gensim 库提供了丰富的函数来比较向量表示,其中常用的方法是余弦相似度(cosine similarity),即两个向量之间夹角的余弦值。通过余弦相似度,我们可以衡量不同向量之间的关系。

以下是一个 mermaid 流程图,展示了使用 Doc2Vec 进行文本处理和向量比较的流程:

graph LR
    A[读取推文数据] --> B[简化文本]
    B --> C[创建 TaggedDocument]
    C --> D[训练 Doc2Vec 模型]
    D --> E[获取向量表示]
    E --> F[计算余弦相似度]
    F --> G[查找最相似的单词或文档]

在前面的代码示例中,我们已经展示了如何使用 model.wv.most_similar 函数来查找与“bad service”最相似的单词。以下是一个更详细的操作步骤说明:
1. 准备数据 :确保已经训练好 Doc2Vec 模型,并且有需要比较的文本。
2. 获取向量表示 :使用 model.infer_vector 函数获取文本的向量表示。
3. 计算余弦相似度 :使用 model.wv.most_similar 函数计算与目标向量最相似的单词或文档。

# 获取新消息的向量表示
badservice = model.infer_vector(['bad', 'service'])

# 查找与“bad service”最相似的单词
similar_words = model.wv.most_similar(['bad', 'service'])
for word, similarity in similar_words:
    print(f"Word: {word}, Similarity: {similarity}")
不同技术的对比与选择

在自然语言处理中,词袋模型、Word2Vec 和 Doc2Vec 等技术各有优缺点,我们需要根据具体的应用场景来选择合适的技术。以下是一个表格,对比了这三种技术的特点:
| 技术 | 优点 | 缺点 | 适用场景 |
| — | — | — | — |
| 词袋模型 | 实现简单,易于理解;可以快速生成向量表示 | 忽略了单词的顺序和上下文信息;向量维度可能会很大 | 对文本的语义理解要求不高,只关注单词出现频率的场景 |
| Word2Vec | 考虑了单词的上下文信息,生成的向量具有语义意义;可以捕捉单词之间的语义关系 | 训练时间较长;需要大量的训练数据 | 需要对单词的语义进行深入理解,如文本分类、情感分析等场景 |
| Doc2Vec | 可以对整个文档进行向量表示;可以利用标签信息 | 训练时间更长;对标签的选择有一定要求 | 需要对文档进行整体表示和比较的场景,如文档聚类、信息检索等 |

实际应用案例分析

为了更好地理解这些技术的应用,我们可以结合前面提到的航空公司推文数据集进行分析。假设我们的目标是对航空公司的服务质量进行情感分析,以下是一个可能的实现步骤:
1. 数据预处理 :使用 simplify_text 函数对推文进行简化处理,去除停用词和规范化大小写。
2. 特征提取 :使用 Doc2Vec 模型将推文转换为向量表示。
3. 模型训练 :使用机器学习模型(如支持向量机、逻辑回归等)对向量表示进行训练,以预测推文的情感倾向(正面、负面或中性)。
4. 模型评估 :使用测试数据集对训练好的模型进行评估,计算准确率、召回率等指标。

以下是一个简化的代码示例:

from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

# 准备特征和标签
X = []
y = []
for (author, airline, msg) in tweets:
    vec = model.infer_vector(simplify_text(msg))
    X.append(vec)
    # 这里假设我们已经有了情感标签,实际应用中需要手动标注或使用其他方法获取
    sentiment = 'positive' if 'good' in msg.lower() else 'negative'
    y.append(sentiment)

# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 训练支持向量机模型
clf = SVC()
clf.fit(X_train, y_train)

# 预测测试集
y_pred = clf.predict(X_test)

# 计算准确率
accuracy = accuracy_score(y_test, y_pred)
print(f"Accuracy: {accuracy}")

总结与展望

通过本文的介绍,我们了解了显式类别变量的识别和处理方法,以及自然语言处理中词袋模型、Word2Vec 和 Doc2Vec 等技术的原理和应用。在数据处理中,正确处理分类变量可以提高数据的存储效率和处理性能;在自然语言处理中,这些技术可以将自然语言文本转换为数值特征,为机器学习模型提供输入。

未来,随着自然语言处理技术的不断发展,我们可以期待更高效、更准确的文本编码方法和模型出现。同时,结合深度学习等技术,我们可以进一步提高自然语言处理的性能和应用范围。例如,使用预训练的语言模型(如 BERT、GPT 等)可以更好地捕捉文本的语义信息,从而在情感分析、信息检索等任务中取得更好的效果。

在实际应用中,我们需要根据具体的问题和数据特点选择合适的技术和方法,并不断进行实验和优化,以达到最佳的效果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值