分析 Kaggle TOP0.1% 如何处理文本数据
感觉大佬的代码写的就是好,在处理数据的方面,首先定义一个 提取特征的类, class Extractor(object):
,然后每一种方法对这个类进行重构,这个类主要结构就是:
class Extractor(object):
def __init__(self, config_fp):
# set feature name
self.feature_name = self.__class__.__name__
# set feature file path
self.data_feature_fp = None
# load configuration file
self.config = configparser.ConfigParser()
self.config.read(config_fp)
# 这个函数什么都没写,就是用来重构的,表示特征的个数
def get_feature_num(self):
assert False, 'Please override function: Extractor.get_feature_num()'
# assert False 后面加字符串就是为了解释哪里出错的,给出错误信息
def extract_row(self, row):
assert False, 'Please override function: Extractor.extract_row()'
# 抽取原始数据的特征
def extract(self, data_set_name, part_num=1, part_id=0):
"""
Extract the feature from original data set
:param data_set_name: name of data set
:param part_num: number of partitions of data
:param part_id: partition ID which will be extracted
:return:
"""
接下来看如何具体的从统计的角度与 NLP 的角度处理数据
统计学的角度处理数据的方法
从统计学的角度考虑主要是单词的频率,数据的次数等等,这里考虑的问题很多,总结来说就是,每种方法的处理套路是,使用分词,然后使用词干提取的方法,将所有的单词进行词干归一化处理。注意,这里是从统计的角度考虑问题,那么就不要考虑到单词的时态问题,词干提取可以更好的表示出现的频率。
主要使用的方法总结,之后我会具体说一下使用的比较复杂的方法:
- Not 类,统计一句话中 ‘not’ 出现的次数
- WordMatchShare 类,两句话中均出现的单词的占所有单词的比例
- TFIDFWordMatchShare 类,与前面的类似,只不过这里加权了文件的出现次数
- Length 类,表示长度的一些数据
- LengthDiff 类表示问题的长度之差
- LengthDiffRate 类,数据上比较长短
- PowerfulWord 这个类是为后面服务的,计算数据中词语的影响力
- PowerfulWordOneSide 类,考虑单词出现的比例以及正确的比例
- PowerfulWordDoubleSideRate 类,考虑两边都出现的单词的比例,以及这些单词对应的 label 的比例
- TFIDF 类,使用 sklearn 中方法直接获取 TFIDF 类
- DulNum 类,计算完全重复的问题的数量
- EnCharCount 类,统计每句话中字母的出现的频率,
- NgramJaccardCoef 类,使用 ngram 的方法计算两个问题之间的距离
- NgramDiceDistance 类,与上面的方法类似,只是计算距离的方法不同
- Distance 类,这里是下面的方法父类,是用于计算句子之间距离的工具
- NgramDistance 类,这个主要是在上面的基础上,结合矩阵的距离的方法
- InterrogativeWords 类,这个主要是统计疑问句的比例
TFIDFWordMatchShare 方法
TFIDFWordMatchShare 这个方法是考虑单词出现在文件的次数,也就是 IDF 的意思,然后用这个加权来表示共同出现的单词的加权的文件的比例,这里具体看下重点的代码就是:
def init_idf(data):
idf = {}
# 先统计了单词的 IDF 值
num_docs = len(data)
for word in idf:
idf[word] = math.log(num_docs / (idf[word] + 1.)) / math.log(2.)
# 这里是一个对数中的换底公式
LogUtil.log("INFO", "idf calculation done, len(idf)=%d" % len(idf))
# 返回一个字典,是整个文件中的单词的,平均每个单词出现在文件中的次数,
# 比如说,5个文件,这个单词一共出现了三次,那么就是 5/3
return idf
def extract_row(self, row):
qwords = {}
# 这里是先统计了单词出现的次数, qword来计算,
# 下面的这个公式计算的是, 同时出现在两个问题中的单词他们所加权的文件总数
# 比如说,上面前面计算 IDF 是对于整个文件来说,单词 'word'的idf值是 5/3,那么对于这一句话来说,'word' 出现了两次,并且 # 'word' 在两个问题均出现,那么这个值就是 10 /3 ,然后对于每个出现的单词计算就可以了
sum_shared_word_in_q1 = sum([q1words[w] * self.idf.get(w, 0) for w in q1words if w in q2words])
sum_shared_word_in_q2 = sum([q2words[w] * self.idf.get(w, 0) for w in q2words if w in q1words])
sum_tol = sum(q1words[w] * self.idf.get(w, 0) for w in q1words) + sum(
q2words[w] * self.idf.get(w, 0) for w in q2words)
if 1e-6 > sum_tol:
return [0.]
else:
return [1.0 * (sum_shared_word_in_q1 + sum_shared_word_in_q2) / sum_tol]
PowerfulWord 方法
这个方法是统计单词的权重及比例,
def generate_powerful_word(data, subset_indexs):
"""
计算数据中词语的影响力,格式如下:
词语 --> [0. 出现语句对数量,1. 出现语句对比例,2. 正确语句对比例,3. 单侧语句对比例,4. 单侧语句对正确比例,
5. 双侧语句对比例,6. 双侧语句对正确比例]
"""
words_power = {}
train_subset_data = data.iloc[subset_indexs, :]
# 取出 subset_indexs中的所有的行
# 然后遍历 subset_indexs 中的所有的行
class PowerfulWordDoubleSide(Extractor):
# 通过设置阈值来提取这句话中关键的单词,然后组成单词向量
def init_powerful_word_dside(pword, thresh_num, thresh_rate):
pword_dside = []
# 出现语句对的数量乘以双侧语句对的比例,得到双侧语句对的数量,
# 计算两边都出现,并且比例高的单词,然后从大到小排序
pword = filter(lambda x: x[1][0] * x[1][5] >= thresh_num, pword)
# 抽取出 pword 中满足条件的所有项目
pword_sort = sorted(pword, key=lambda d: d[1][6], reverse=True)
# 表示按照降序排序
pword_dside.extend(map(lambda x: x[0], filter(lambda x: x[1][6] >= thresh_rate, pword_sort)))
# 在list的结尾追加一序列的值
LogUtil.log('INFO', 'Double side power words(%d): %s' % (len(pword_dside), str(pword_dside)))
return pword_dside
句子之间的距离的计算
由于之前自己对句子之间的距离的了解也比较少,所以这里写的详细一点,这里的主要思想是
class Distance(Extractor):
def __init__(self, config_fp, distance_mode):
Extractor.__init__(self, config_fp)
self.feature_name += '_%s' % distance_mode
self.valid_distance_mode = ['edit_dist', 'compression_dist']
# 这两个方法是计算两个字符串之间的距离使用的,其中 'edit_dist' 直接调用的一个方法,而'compression_dist'通过简单计算
# 就可以得到
assert distance_mode in self.valid_distance_mode, "Wrong aggregation_mode: %s" % distance_mode
# 初始化参数
self.distance_mode = distance_mode
# 使用不同的方法来计算字符串之间的距离
self.distance_func = getattr(DistanceUtil, self.distance_mode)
def extract_row(self, row):
q1 = str(row['question1']).strip()
q2 = str(row['question2']).strip()
q1_stem = ' '.join([snowball_stemmer.stem(word).encode('utf-8') for word in
nltk.word_tokenize(TextPreProcessor.clean_text(str(row['question1']).decode('utf-8')))])
q2_stem = ' '.join([snowball_stemmer.stem(word).encode('utf-8') for word in
nltk.word_tokenize(TextPreProcessor.clean_text(str(row['question2']).decode('utf-8')))])
# 先分词,然后将单词用空格连成句子,假装是句子
return [self.distance_func(q1, q2), self.distance_func(q1_stem, q2_stem)]
def get_feature_num(self):
return 2
class NgramDistance(Distance):
# 这里没有构造函数,子类直接调用父类的构造函数
def extract_row(self, row):
# 使用词干提取
fs = list()
aggregation_modes_outer = ["mean", "max", "min", "median"]
aggregation_modes_inner = ["mean", "std", "max", "min", "median"]
# 这些主要是 np 中矩阵的一些方法,用于数据处理均值,最大值,最小值,中位数,矩阵的标准差 等等
for n_ngram in range(1, 4):
q1_ngrams = NgramUtil.ngrams(q1_words, n_ngram)
q2_ngrams = NgramUtil.ngrams(q2_words, n_ngram)
val_list = list()
for w1 in q1_ngrams:
_val_list = list()
for w2 in q2_ngrams:
s = self.distance_func(w1, w2)
# 两个句子在 ngram 下面的距离,然后存起来
_val_list.append(s)
if len(_val_list) == 0:
_val_list = [MISSING_VALUE_NUMERIC]
val_list.append(_val_list)
if len(val_list) == 0:
val_list = [[MISSING_VALUE_NUMERIC]]
# val_list 存的就是在 q1_ngrams 下每两个句子之间的距离,组成一个矩阵
for mode_inner in aggregation_modes_inner:
tmp = list()
for l in val_list:
tmp.append(MathUtil.aggregate(l, mode_inner))
fs.extend(MathUtil.aggregate(tmp, aggregation_modes_outer))
return fs
def get_feature_num(self):
return 4 * 5
NLP 角度处理数据的方法
这里主要考虑的是解析树的构成,构建一颗解析树,从语句的解析树提取句子的特征,
def init_tree_properties(tree_fp):
features = {}
f = open(tree_fp)
for line in f:
[qid, json_s] = line.split(' ', 1)
# 分割一次,分成两个
features[qid] = []
root = -1
parent = {}
indegree = {}
# calculate in-degree and find father
# 删除开头与结尾的空格
if 0 < len(json_s.strip()):
tree_obj = json.loads(json_s)
# 将一个JSON编码的字符串转换回一个Python数据结构:
# 返回一个字典
assert len(tree_obj) <= 1
tree_obj = tree_obj[0]
for k, r in sorted(tree_obj.items(), key=lambda x: int(x[0]))[1:]:
if r['word'] is None:
continue
head = int(r['head'])
k = int(k)
if 0 == head:
root = k
parent[k] = head
indegree[head] = indegree.get(head, 0) + 1
# calculate number of leaves
n_child = 0
for i in parent:
if i not in indegree:
n_child += 1
# calculate the depth of a tree
depth = 0
for i in parent:
if i not in indegree:
temp_id = i
temp_depth = 0
while (temp_id in parent) and (0 != parent[temp_id]):
temp_depth += 1
temp_id = parent[temp_id]
depth = max(depth, temp_depth)
# calculate the in-degree of root
n_root_braches = indegree.get(root, 0)
# calculate the max in-degree
n_max_braches = 0
if 0 < len(indegree):
n_max_braches = max(indegree.values())
features[str(qid)] = [n_child, depth, n_root_braches, n_max_braches]
f.close()
return features
分析 Kaggle TOP0.1% 如何处理文本数据的更多相关文章
- J2EE综合:如何处理大数据量的查询
在实际的任何一个系统中,查询都是必不可少的一个功能,而查询设计的好坏又影响到系统的响应时间和性能这两个要害指标,尤其是当数据量变得越来越大时,于是如何处理大数据量的查询成了每个系统架构设计时都必须面对 ...
- NLP相关问题中文本数据特征表达初探
1. NLP问题简介 0x1:NLP问题都包括哪些内涵 人们对真实世界的感知被成为感知世界,而人们用语言表达出自己的感知视为文本数据.那么反过来,NLP,或者更精确地表达为文本挖掘,则是从文本数据出发 ...
- scikit-learning教程(三)使用文本数据
使用文本数据 本指南的目标是探讨scikit-learn 一个实际任务中的一些主要工具:分析二十个不同主题的文本文档(新闻组帖子)集合. 在本节中,我们将看到如何: 加载文件内容和类别 提取适用于机器 ...
- Bulk Insert:将文本数据(csv和txt)导入到数据库中
将文本数据导入到数据库中的方法有很多,将文本格式(csv和txt)导入到SQL Server中,bulk insert是最简单的实现方法 1,bulk insert命令,经过简化如下 BULK INS ...
- 业务人员自助BI分析不够用,还要自助数据准备?
自助式BI工具,可以帮助业务人员充分了解和利用企业数据,通过可视化操作,拖拖拽拽来新建分析,生成可视化的报表,帮助企业决策.但近几年的调查研究发现,拥有强大分析策略和模型的产品,比如Tableau.q ...
- JAVASE02-Unit08: 文本数据IO操作 、 异常处理
Unit08: 文本数据IO操作 . 异常处理 * java.io.ObjectOutputStream * 对象输出流,作用是进行对象序列化 package day08; import java.i ...
- JAVASE02-Unit07: 基本IO操作 、 文本数据IO操作
基本IO操作 . 文本数据IO操作 java标准IO(input/output)操作 package day07; import java.io.FileOutputStream; import ja ...
- 《BI那点儿事》SSRS图表和仪表——雷达图分析三国超一流谋士、统帅数据(图文并茂)
雷达图分析三国超一流谋士.统帅数据,献给广大的三国爱好者们,希望喜欢三国的朋友一起讨论,加深对传奇三国时代的了解 建立数据环境: -- 抽取三国超一流谋士TOP 10数据 DECLARE @t1 TA ...
- 10、NFC技术:读写NFC标签中的文本数据
代码实现过程如下: 读写NFC标签的纯文本数据.java import java.nio.charset.Charset; import java.util.Locale; import androi ...
随机推荐
- 《JavaScript高级程序设计》笔记:高级技巧
高级函数 安全的类型检测 在任何值上调用Object原生的toString()方法,都会返回一个[object NativeConstructorName]格式的字符串.每个类在内部都有一个[[Cla ...
- Springboot生成二维码并下载图片png支持打包成zip
pom.xml <!--二维码--> <dependency> <groupId>com.google.zxing</groupId> <arti ...
- XenCenter安装VM
XenServer是服务器"虚拟化系统".系统设置为Linux_x86-64即可安装XenServer 和VMware ESX/ESXi有点不同的是,XenServer 不能在Xe ...
- Python 栈、队列的实现
在python中,列表既可以作为栈使用,又可以作为队列使用. 把列表作为栈使用 栈:后进先出 stack=[1,2,3] stack.append(4) #入栈,以列表尾部为栈顶 print(stac ...
- 15 Android系统安全(简要)
Android的用户和第三方软件,Android组件和数据安全 手机root后的问题:1.系统不稳定,2.病毒入侵,3.数据泄露 Root原理: Root分两类:1.临时root,2.永久root R ...
- Nexus安装和使用
1.前言 最近项目需要搭建maven私服,方便管理后期团队成员使用上传自己的包,因此决定使用nexus来搭建私服,搭建好的nexus地址. 2.准备工作 阿里云服务器ECS一台 1核CPU 2G内存( ...
- Kubernetes学习之路(28)之镜像仓库Harbor部署
Harbor的部署 官方文档 Harbor有两种安装的方式: 在线安装:直接从Docker Hub下载Harbor的镜像,并启动. 离线安装:在官网上下载离线安装包其地址为:https://githu ...
- LVS负载均衡部署
一.lvs-nat模式 1.1.环境介绍 本实验用三台虚拟机完成,一台虚拟机模拟lvs调度器,两块网卡,一块模拟公网一块模拟私网,公网地址192.168.0.201/24,私网地址192.168.4. ...
- Go编程基础(介绍和安装)
Michaelhbjian 2018.10.07 19:41 字数 892 阅读 317评论 0喜欢 0 Go(又称Golang[3])是Google开发的一种静态强类型.编译型.并发型,并具有垃圾回 ...
- Beta冲刺(5/7)——2019.5.26
所属课程 软件工程1916|W(福州大学) 作业要求 Beta冲刺(5/7)--2019.5.26 团队名称 待就业六人组 1.团队信息 团队名称:待就业六人组 团队描述:同舟共济扬帆起,乘风破浪万里 ...