当前位置:   article > 正文

处理文本数据_文本数据处理的常用方法有哪些?

文本数据处理的常用方法有哪些?

文本是常用的序列数据之一
可理解为字符序列或单词序列
映射书面语言的统计结构
文本向量化:将文本转换成数值张量的过程
实现方法

  • 文本分割成单词/字符,并转换为一个向量
  • 提取单词或字符的n-gram,将每个n-gram转换成一个向量
  • n-gram是多个连续单词/字符的集合(n-gram之间可重合)

将文本分解成单元叫做标记(token)
将文本分解成标记的过程叫做分词(tokenization)
所有文本向量化过程都是应用某种分词方案,然后将数值向量与生成标记相关联

  • 对标记做one-hot编码
  • 标记嵌入[token embedding,通常只用于单词,叫做词嵌入word embedding]

n-gram

  • 从一个句子提取N个或更少的连续单词的集合
  • 句子被分解为2-grams/3-grams(二元/三元句法)的集合,分别叫做二元词法袋(bag-of-2-grams)及三元词法袋(***)
  • 词袋是一种不保存顺序的分词方法,常用于浅层语言处理模型

1.单词级的one-hot编码示例

#单词级的one-hot编码
import numpy as np
samples=['the cat sat on the mat','The dog ate my homework']

token_index={}
for sample in samples:
  for word in sample.split():
    if word not in token_index:
      token_index[word]=len(token_index)+1  #为每个唯一单词指定唯一索引
      
      
max_length=10  #只考虑样本的前max_length个单词

results=np.zeros(shape=(len(samples),
                        max_length,
                        max(token_index.values())+1))
                        
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
#字符级的one-hot编码
import string

samples=['the cat sat on the mat','The dog ate my homework']
characters=string.printable  #所有可打印的ASCII字符
token_index=dict(zip(range(1,len(characters)+1),characters))

max_length=50
results=np.zeros((len(samples),max_length,max(token_index.keys())+1))
for i,sample in enumerate(samples):
  for j,character in enumerate(sample):
    index=token_index.get(character)
    results[i,j,index]=1
    #print(j,character)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
#用keras实现单词级的one-hot编码
from keras.preprocessing.text import Tokenizer

samples=['the cat sat on the mat','The dog ate my homework']
#创建一个分词器,设置只考虑前1000个单词
tokenizer=Tokenizer(num_words=1000)
#构建单词索引
tokenizer.fit_on_texts(samples)
#将字符串转换为整数索引组成的列表
sequences=tokenizer.texts_to_sequences(samples)
#也可以直接得到one-hot二进制表示
one_hot_results=tokenizer.texts_to_matrix(samples,mode='binary')
#找回单词索引
word_index=tokenizer.word_index
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

使用词嵌入
单词与向量关联的另一种方法,使用密集的词向量(word vector)也叫词嵌入(word embedding)
onehot编码得到的是二进制的,稀疏的,维度很高
词嵌入是从数据中学习得到的
获取词嵌入的方法:

  • 在完成主任务(文档分类、情感预测)的同时学习词嵌入。开始是随机词向量,然后对词向量进行学习,学习方式等同于学习神经网络权重
  • 预训练词嵌入:在不同待解决问题的机器学习任务上预计算好词嵌入,然后加载到模型中
    1.利用embedding层学习词嵌入
    词之间的空间关系表示词之间的语义关系
    词嵌入将语言映射到几何空间中
#将一个embedding层实例化
from keras.layers import Embedding
#Embedding至少需要需要两个参数,标记的个数(1000)和嵌入的维度(64
)
embedding_layer=Embedding(1000,64)
  • 1
  • 2
  • 3
  • 4
  • 5

Embedding层可以理解为一个字典,将整数索引映射为密集向量,
实际上是一种字典查找:单词索引->Embedding层->对应的词向量
2. 使用与训练的词嵌入
自然语言处理中使用预训练词嵌入,原理与图像分类中使用预训练的卷积神经网络一样

案例:从原始文本到词嵌入
#下载IMDB原始数据的标签
import os

imdb_dir='****'
train_dir='***'

labels=[]
texts=[]

for label_type in['neg','pos']:
	dir_name=os.path.join(train_dir,label_type)
	for fname in os.listdir(dir_name):
		if fname[-4:]=='.txt':
			f=open(os.path.join(dir_name,fname))
			texts.append(f.read())
			f.close()
			if label_type=='neg':
				labes.append(0)
			else:
				label.append(1)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
#对IMDB原始数据文本进行分词
#对IMDB原始数据文本进行分词
from keras.preprocessing.text import Tokenizer
from keras.preprocessing.sequence import  pad_sequences
import numpy as np

maxlen=100   #阶段100个单词后的评论
training_samples=200      #在200个样本上训练
validation_samples=10000     #在10000个样本上验证
max_words=10000        #只考虑数据集中前一万个常见单词

tokenizer=Tokenizer(num_words=max_words)
tokenizer.fit_on_texts(texts)
sequences=tokenizer.texts_to_sequences(texts)

word_index=tokenizer.word_index
print("found %s unique tokens."%len(word_index))

data=pad_sequeces(sequences,maxlen=maxlen)

labels=np.asarray(labels)

print("shape of data tensor:",data.shape)
print("shape of label tensor.",labels.shape)

#将数据划分为训练集和测试集,但首先要打乱数据,因为一开始是排好序的
indices=np.arange(data.shape[0])
np.random.shuffle(indices)
data=data[indices]
label=labels[indices]

x_train=data[:training_samples]
y_train=labels[:training_samples]
x_val=data[training_samples:training_samples+validation_samples]
y_val=labels[training_samples:training_samples+validation_samples]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

下载词嵌入
下载维基百科词嵌入,包含40万个单词的100维向量,

#对嵌入进行预处理

解析解压后的文件,构建一个单词映射维其向量表示的索引
glove_dir='downloads/glove/.6B'
embedding_index={}
f=open(os.path.join(glove_dir,'glove.6B.100d.txt'))
for line in f:
	values=line.split()
	word=values[0]
	coefs=np.asarray(values[1:],dtype='float32')
	embeddings_index[word]=coefs
f.close()

print('Found %s word vectors.'%len(embedding_index))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

构建一个可以加载到embedding层中的嵌入矩阵,形状为(max_words,embedding_dim)的矩阵
对于单词索引为i的单词,矩阵元素i就是单词对应的embedding_dim维向量
索引0不代表任何单词或标记,只是一个占位符

#准备词嵌入矩阵
embedding=100

embedding_matrix=np.zeros((max_words,embedding_dim))
for word,i in word_index.get(word):
	if i<max_words:
		embedding_vector=embedding_index.get(word)
		if embedding_vector is not None:
		#嵌入索引中找不到的词,其嵌入矩阵全为0
			embedding_matrix[i]=embedding_vector

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
#定义模型
from keras,models import Sequensial
from keras.layers import Embedding,Flatten,Dense

model=Sequensial()
model.add(Embedding(max_words,embedding_dim,input_length=maxlen))
model.add(Flatten())
model.add(Dense(32,activation='relu'))
model.add(Dense(1,activation='sigmoid'))
model.summary()

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

在模型中加载Glove嵌入
Embedding层只有一个权重矩阵(二维浮点数),其中每个元素i是与索引i相关联的词向量

model.layers[0].set_weights([embedding_matrix])
#冻结embedding层
#如果一个模型的一部分是经过预训练的(embedding),而另一部分是经过随机初始化的(分类器),那么在训练期间不应该更新预训练的部分,以避免丢失他们所保留的信息
#随机初始化层会引起较大梯度更新,破坏已学到的特征
model.layers[0].trainable=False

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

预训练模型与评估

model.compile(optimizer='rmsprop',
						loss='binary_crossentropy'
						metrics=['acc'])
history=model.fit(x_train,y_train,
							epochs=10,
							batch_size=32,
							validation_data=(x_val,y_val)
							)
model.save_weights('pre_trained_glove_model.h5')

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/756190
推荐阅读
相关标签
  

闽ICP备14008679号