文本离散表示(二):新闻语料的one-hot编码
上一篇博客介绍了文本离散表示的one-hot、TF-IDF和n-gram方法,在这篇文章里,我做了一个对新闻文本进行one-hot编码的小实践。
文本的one-hot相对而言比较简单,我用了两种方法,一种是自己造轮子,第二种是用深度学习框架keras来做。同时,我发现尽管sklearn可以实现对特征向量的one-hot,但并不适用于文本的处理。
代码和新闻文本文件可到我github主页下载:https://github.com/DengYangyong/one_hot_distribution。发现新闻文本文件好大。。。不该上传完整的。
一、关于sklearn进行one-hot
在翻阅介绍文本one-hot的博客时,看到有博主举了一个用sklearn实现one-hot的小例子,我也把代码运行了一遍。
代码和输出结果如下:
from sklearn import preprocessing
import numpy as np enc = preprocessing.OneHotEncoder() # 创建对象
array1 = np.asarray([[0,0,3],[1,1,0],[0,2,1],[1,0,2]])
enc.fit(array1) # 拟合
array2 = enc.transform([[0,1,3]]).toarray() # 转化
print("4个样本的特征向量是:\n", array1,'\n')
print('对第5个样本的特征向量进行one-hot:', array2)
输出结果:
4个样本的特征向量是:
[[0 0 3]
[1 1 0]
[0 2 1]
[1 0 2]] 对第5个样本的特征向量进行one-hot: [[1. 0. 0. 1. 0. 0. 0. 0. 1.]]
什么意思呢?拿西瓜做为例子,有4个西瓜,每个西瓜取3个特征,{"瓜籽": ['有', '无'], "根蒂": ['硬挺','蜷缩','枯萎'], "颜色": ['白','黑','绿','黄']},第一个特征有两个属性,用0和1表示,第二个特征有三个属性,用0、1和2表示,第三个特征有4个属性,用0-3表示。所以array1这个4*3的数组表示4个西瓜的特征向量,4表示样本数,3表示特征数。那么在进行one-hot时,每个样本的向量的维度是9(2+3+4)维,也就是属性的数量进行累加。样本第一个特征取0时,表示为[1,0]; 第二个特征为1时,表示为[0,1,0];第三个特征为3时,表示为[0,0,0,1],然后按顺序拼成一个向量,就得到了[1,0,0,1,0,0,0,0,1],这个9维的向量也就是第5个西瓜的特征向量的one-hot。
那可以用来做文本的one-hot吗?不可以,因为上面的例子是把向量转为了one-hot,而文本one-hot是把类似[['天', '气', '很','好'],['我','爱','自','然','语','言','处','理']]这样的形式转为one-hot,这样的形式转为向量要么是词频矩阵,要么直接就是one-hot。所以sklearn的这个函数是没法做文本的one-hot的。
二、自己造轮子实现文本one-hot
这次是对新闻文本进行one-hot,cnews.train.txt 这个文件中有几十万篇新闻文本,有10类新闻,分别是 ['体育', '财经', '房产', '家居', '教育', '科技', '时尚', '时政', '游戏', '娱乐']。文件的每一行就是一篇新闻,开头两个字是类别,后面是新闻内容,中间用"\t"隔开。比如第一行的内容:
体育 马晓旭意外受伤让国奥警惕 无奈大雨格外青睐殷家军记者傅亚雨沈阳报道 来到沈阳,国奥队依然没有摆脱雨水的困扰。......
考虑到内容较大,因此只读取1000篇新闻文本进行one-hot。经过了几个步骤:把文本处理成char-level的列表——取前1000个词频最高的字作为字典——为字典的每个字分配索引——进行one-hot编码。
最终得到的是1000*1000维的one-hot数组。打开保存的文本一看,密密麻麻的0,星星点点的1,足以看到数据的稀疏性。
import numpy as np
import os text_path = os.getcwd()+os.sep+'cnews'+os.sep
fp = open(text_path+'cnews.train.txt','r',encoding='utf8')
fout = open(text_path+'cnews_one_hot_diy.txt','w',encoding='utf8') #把新闻处理成char_level的列表,去除停用词
# 输出:[['马', '晓', '旭', '意', '外', '受', '伤', '国', '奥', '警', '惕', '', '奈',...],[],...[]]
news_list = []
news_count =0
fp_stop = open("ChineseStopWords.txt","r",encoding="utf8") #打开中文停用词表用于过滤
dict_stopwords = [stopwords.strip() for stopwords in fp_stop.readlines()]
for text in fp.readlines() :
if text.strip() and news_count < 1000: #只取前1000篇新闻文本
label,news = text.strip().split('\t') #把类别标签和文本分开
news_list.append([char.strip() for char in list(news) if char not in dict_stopwords]) # 把文本切成一个个字并过滤停用词
news_count += 1
print("读取了cnews.train.txt 中的"+str(news_count)+"条新闻。\n")
fp_stop.close()
fp.close() #把每个字的词频统计出来
# 输出:{'马': 1379, '晓': 31, '旭': 25, '意': 855, '外': 1218, '受': 872, '伤': 1169, '国': 1046, ...}
token_count = {}
for list_ in news_list:
for word in list_:
if word not in token_count:
token_count[word] = 1
else:
token_count[word] += 1 # 按词频对字进行排序,取前1000个词频最高的字
# token_sort输出:{'分': 8759, '球': 8193, '场': 7862, '斯': 7731, '赛': 7040, '中': 6537, '队': 6169, ...}
# dict.items()是把字典转化为元素为元祖的列表,然后按照元祖的第2个值进行排序,即词频。
token_tuple = sorted(token_count.items(), key=lambda item: item[1],reverse=True)
# 取前1000个词频最高的字,转化为字典。
token_sort = dict(token_tuple[:1000]) #为每一个字分配索引,不为0分配字,貌似是深度学习中的习惯。
# 输出:{'分': 1, '球': 2, '场': 3, '斯': 4, '赛': 5, '中': 6, '队': 7, '时': 8, '出': 9, '篮': 10, '火': 11, '次': 12, '前': 13, ...}
token_index = dict(zip(token_sort.keys(),range(1,len(token_sort)))) # 进行进行one-hot编码
# result[0]输出为:array([0., 1., 1., 1., 0., 1., 1., 1., 1., 1., 0., 0., 1., 1., 0., 0., 0.,..])
result = np.zeros(shape=(1000,1000))
for i,list_ in enumerate(news_list):
for word in list_:
if word in token_index:
j = token_index[word]
result[i,j] = 1 # 用numpy 将one-hot按int格式保存,方便下次打开为ndarray格式,而不是文本。
np.savetxt(text_path+"cnews_one_hot_diy.txt",result,fmt="%d")
fout.close()
第一篇文本的one-hot:
三、 用keras实现one-hot
使用keras需要先安装tensorflow,用宇宙最牛公司的深度学习框架来做one-hot,有杀鸡用牛刀的感觉,所以说这是豪华版。不过可以通过这个过程来掌握一些python库的用法,也是非常有意思的。过程比较简单,就两步:文本处理成char-level的列表——进行one-hot编码。
不多说了,上代码!
#coding=utf8
from keras.preprocessing.text import Tokenizer
from collections import Counter
import os
from itertools import chain
import numpy as np text_path = os.getcwd()+os.sep+'cnews'+os.sep
fp = open(text_path+'cnews.train.txt','r',encoding='utf8')
fout = open(text_path+'cnews_one_hot.txt','w',encoding='utf8')
news_list = [] #把新闻处理成char_level的列表,去除停用词
# 输出:[['马', '晓', '旭', '意', '外', '受', '伤', '国', '奥', '警', '惕', '', '奈',...],[],...[]]
news_count =0
fp_stop = open("ChineseStopWords.txt","r",encoding="utf8")
dict_stopwords = [stopwords.strip() for stopwords in fp_stop.readlines()]
for text in fp.readlines() :
if text.strip() and news_count < 1000:
label,news = text.strip().split('\t')
news_list.append([char.strip() for char in list(news) if char not in dict_stopwords])
news_count += 1
print("读取了cnews.train.txt 中的"+str(news_count)+"条新闻。\n")
fp_stop.close()
fp.close() # 统计并查看这些新闻中所有的字的个数
# 其实对于这个问题而言不重要
counter = Counter(list(chain.from_iterable(news_list)))
char_count = len(counter)
print(str(news_count)+"条新闻中有"+str(char_count)+"个不同的字。\n") #用keras进行one-hot编码,取前1000个频率最高的字作为字典
tokenizer=Tokenizer(num_words=1000)
tokenizer.fit_on_texts(news_list)
one_hot_results = tokenizer.texts_to_matrix(news_list,mode='binary') #直接由[['马', '晓', '旭', '意', ...],..[]]得到one-hot矩阵,还是方便。
print("独热编码后每条新闻的向量长度为:", one_hot_results.shape[1],'\n') # 用numpy把array数组保存,方便下次再以arry的格式打开,而不是字符串格式。
np.savetxt(text_path+"cnews_one_hot.txt",one_hot_results,fmt="%d")
fout.close() # 将保存的array数组文件打开
news_one_hot = np.loadtxt(text_path+"cnews_one_hot.txt",dtype=float)
print("数据的格式为", type(news_one_hot))
打印的内容:
读取了cnews.train.txt 中的1000条新闻。 1000条新闻中有3164个不同的字。 独热编码后每条新闻的向量长度为: 1000 数据的格式为 <class 'numpy.ndarray'>
第一篇文本的one-hot:
参考资料:
《Python深度学习》
文本离散表示(二):新闻语料的one-hot编码的更多相关文章
- 【NLP】3000篇搜狐新闻语料数据预处理器的python实现
3000篇搜狐新闻语料数据预处理器的python实现 白宁超 2017年5月5日17:20:04 摘要: 关于自然语言处理模型训练亦或是数据挖掘.文本处理等等,均离不开数据清洗,数据预处理的工作.这里 ...
- 文本离散表示(三):TF-IDF结合n-gram进行关键词提取和文本相似度分析
这是文本离散表示的第二篇实战文章,要做的是运用TF-IDF算法结合n-gram,求几篇文档的TF-IDF矩阵,然后提取出各篇文档的关键词,并计算各篇文档之间的余弦距离,分析其相似度. TF-IDF与n ...
- 【JAVA编码】 JAVA字符编码系列二:Unicode,ISO-8859,GBK,UTF-8编码及相互转换
http://blog.csdn.net/qinysong/article/details/1179489 这两天抽时间又总结/整理了一下各种编码的实际编码方式,和在Java应用中的使用情况,在这里记 ...
- JAVA字符编码二:Unicode,ISO-8859,GBK,UTF-8编码及相互转换
第二篇:JAVA字符编码系列二:Unicode,ISO-8859-1,GBK,UTF-8编码及相互转换 1.函数介绍 在Java中,字符串用统一的Unicode编码,每个字符占用两个字节,与编码有 ...
- 文本离散表示(一):词袋模型(bag of words)
一.文本表示 文本表示的意思是把字词处理成向量或矩阵,以便计算机能进行处理.文本表示是自然语言处理的开始环节. 文本表示按照细粒度划分,一般可分为字级别.词语级别和句子级别的文本表示.字级别(char ...
- Ajax属性和函数以及 返回值之XML格式和文本格式(二)
(一) client请求文本之json格式:接收到json格式,再有js解析(详细先eval成对象,然后.就可以) var text = this.responseText; var book = e ...
- [置顶]
【机器学习PAI实践七】文本分析算法实现新闻自动分类
一.背景 新闻分类是文本挖掘领域较为常见的场景.目前很多媒体或是内容生产商对于新闻这种文本的分类常常采用人肉打标的方式,消耗了大量的人力资源.本文尝试通过智能的文本挖掘算法对于新闻文本进行分类.无需任 ...
- 文本情感分析(二):基于word2vec、glove和fasttext词向量的文本表示
上一篇博客用词袋模型,包括词频矩阵.Tf-Idf矩阵.LSA和n-gram构造文本特征,做了Kaggle上的电影评论情感分类题. 这篇博客还是关于文本特征工程的,用词嵌入的方法来构造文本特征,也就是用 ...
- C语言 文本字符串存入二维数组
字符串存入数组 文本内容: line1_1 line1_2line2_1 line2_2line3_1 line3_2line4_1 line4_2line5_1 line5_2line6_1 lin ...
随机推荐
- 问题(一) DebugAugmenter
问题: DebugAugmenter的作用是什么?是任何一个自创建的变量都可以取代它还是它有特定含义? public class DebugAugmenter Test { @Test public ...
- java集合之ArrayList,TreeSet和HashMap分析
java集合是一个重点和难点,如果我们刻意记住所有的用法与区别则是不太现实的,之前一直在使用相关的集合类,但是没有仔细研究区别,现在来把平时使用比较频繁的一些集合做一下分析和总结,目的就是以后在需要使 ...
- BZOJ_1826_[JSOI2010]缓存交换 _线段树+贪心
BZOJ_1826_[JSOI2010]缓存交换 _线段树+贪心 Description 在计算机中,CPU只能和高速缓存Cache直接交换数据.当所需的内存单元不在Cache中时,则需要从主存里把数 ...
- ES6知识整理(1)--let和const命令
最近准备在业余空闲时间里一边学习ES6,一边整理相关知识.只有整理过的学习才是有效的学习.也就是学习之后要使用和整理成文,才是正在的学到了... 那么现在开始 LINK START!(首先是第一讲,前 ...
- Caffe初学者第一部:Ubuntu14.04上安装caffe(CPU)+Python的详细过程 (亲测成功, 20180524更新)
前言: 最近在学习深度学习,最先要解决的当然是开源框架的环境安装了.之前一直在学习谷歌的Tensorflow开源框架,最近实验中需要跟别人的算法比较,下载的别人的代码很多都是Caffe的,所以想着搭建 ...
- java的8种基础类型
一.基础类型 Java 是一种强类型语言 . 这就意味着必须为每一个变量声明一种类型 : 在 Java 中,一共有 8种基本类型 ( primitive type ) , 其中有 4 种整型 . 2 ...
- python接口自动化(二十四)--unittest断言——中(详解)
简介 上一篇通过简单的案例给小伙伴们介绍了一下unittest断言,这篇我们将通过结合和围绕实际的工作来进行unittest的断言.这里以获取城市天气预报的接口为例,设计了 2 个用例,一个是查询北京 ...
- Tensorflow源码解析1 -- 内核架构和源码结构
1 主流深度学习框架对比 当今的软件开发基本都是分层化和模块化的,应用层开发会基于框架层.比如开发Linux Driver会基于Linux kernel,开发Android app会基于Android ...
- MySQL安装及环境搭建
一.Windows 上安装 MySQL Windows 上安装 MySQL 相对简单,最新版本下载地址: 官网:https://dev.mysql.com/downloads/mysql/ 下载步骤: ...
- LeetCode算法题-Subdomain Visit Count(Java实现)
这是悦乐书的第320次更新,第341篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第189题(顺位题号是811).像"discuss.leetcode.com& ...