感觉大佬的代码写的就是好,在处理数据的方面,首先定义一个 提取特征的类, 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 的角度处理数据

统计学的角度处理数据的方法

从统计学的角度考虑主要是单词的频率,数据的次数等等,这里考虑的问题很多,总结来说就是,每种方法的处理套路是,使用分词,然后使用词干提取的方法,将所有的单词进行词干归一化处理。注意,这里是从统计的角度考虑问题,那么就不要考虑到单词的时态问题,词干提取可以更好的表示出现的频率。

主要使用的方法总结,之后我会具体说一下使用的比较复杂的方法:

  1. Not 类,统计一句话中 ‘not’ 出现的次数
  2. WordMatchShare 类,两句话中均出现的单词的占所有单词的比例
  3. TFIDFWordMatchShare 类,与前面的类似,只不过这里加权了文件的出现次数
  4. Length 类,表示长度的一些数据
  5. LengthDiff 类表示问题的长度之差
  6. LengthDiffRate 类,数据上比较长短
  7. PowerfulWord 这个类是为后面服务的,计算数据中词语的影响力
  8. PowerfulWordOneSide 类,考虑单词出现的比例以及正确的比例
  9. PowerfulWordDoubleSideRate 类,考虑两边都出现的单词的比例,以及这些单词对应的 label 的比例
  10. TFIDF 类,使用 sklearn 中方法直接获取 TFIDF 类
  11. DulNum 类,计算完全重复的问题的数量
  12. EnCharCount 类,统计每句话中字母的出现的频率,
  13. NgramJaccardCoef 类,使用 ngram 的方法计算两个问题之间的距离
  14. NgramDiceDistance 类,与上面的方法类似,只是计算距离的方法不同
  15. Distance 类,这里是下面的方法父类,是用于计算句子之间距离的工具
  16. NgramDistance 类,这个主要是在上面的基础上,结合矩阵的距离的方法
  17. 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% 如何处理文本数据的更多相关文章

  1. J2EE综合:如何处理大数据量的查询

    在实际的任何一个系统中,查询都是必不可少的一个功能,而查询设计的好坏又影响到系统的响应时间和性能这两个要害指标,尤其是当数据量变得越来越大时,于是如何处理大数据量的查询成了每个系统架构设计时都必须面对 ...

  2. NLP相关问题中文本数据特征表达初探

    1. NLP问题简介 0x1:NLP问题都包括哪些内涵 人们对真实世界的感知被成为感知世界,而人们用语言表达出自己的感知视为文本数据.那么反过来,NLP,或者更精确地表达为文本挖掘,则是从文本数据出发 ...

  3. scikit-learning教程(三)使用文本数据

    使用文本数据 本指南的目标是探讨scikit-learn 一个实际任务中的一些主要工具:分析二十个不同主题的文本文档(新闻组帖子)集合. 在本节中,我们将看到如何: 加载文件内容和类别 提取适用于机器 ...

  4. Bulk Insert:将文本数据(csv和txt)导入到数据库中

    将文本数据导入到数据库中的方法有很多,将文本格式(csv和txt)导入到SQL Server中,bulk insert是最简单的实现方法 1,bulk insert命令,经过简化如下 BULK INS ...

  5. 业务人员自助BI分析不够用,还要自助数据准备?

    自助式BI工具,可以帮助业务人员充分了解和利用企业数据,通过可视化操作,拖拖拽拽来新建分析,生成可视化的报表,帮助企业决策.但近几年的调查研究发现,拥有强大分析策略和模型的产品,比如Tableau.q ...

  6. JAVASE02-Unit08: 文本数据IO操作 、 异常处理

    Unit08: 文本数据IO操作 . 异常处理 * java.io.ObjectOutputStream * 对象输出流,作用是进行对象序列化 package day08; import java.i ...

  7. JAVASE02-Unit07: 基本IO操作 、 文本数据IO操作

    基本IO操作 . 文本数据IO操作 java标准IO(input/output)操作 package day07; import java.io.FileOutputStream; import ja ...

  8. 《BI那点儿事》SSRS图表和仪表——雷达图分析三国超一流谋士、统帅数据(图文并茂)

    雷达图分析三国超一流谋士.统帅数据,献给广大的三国爱好者们,希望喜欢三国的朋友一起讨论,加深对传奇三国时代的了解 建立数据环境: -- 抽取三国超一流谋士TOP 10数据 DECLARE @t1 TA ...

  9. 10、NFC技术:读写NFC标签中的文本数据

    代码实现过程如下: 读写NFC标签的纯文本数据.java import java.nio.charset.Charset; import java.util.Locale; import androi ...

随机推荐

  1. 推荐一些github上的免费好书

    本文转载自公众号:跟着小一写bug.  熬夜等于慢性自杀,那熬夜和喜欢的人说话,算不算是慢性殉情?        晚上好 小一来啦 有木有想哀家 其实今晚小一有个拳击课 可是 由于项目明天要演示 调一 ...

  2. LP线性规划初识

    认识LP 线性规划(Linear Programming) 特指目标函数和约束条件皆为线性的最优化问题. 目标函数: 多个变量形成的函数 约束条件: 由多个等式/不等式形成的约束条件 线性规划: 在线 ...

  3. 第一册:lesson 135.

    原文:The latest report. question:Is Karen Marsh going to retire,do you think? Are you really going to ...

  4. Httpd服务入门知识-Httpd服务常见配置案例之定义路径别名

    Httpd服务入门知识-Httpd服务常见配置案例之定义路径别名 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任.   一.创建测试数据 [root@node101.yinzhengj ...

  5. SpringCloud2.0 Eureka Server 服务中心 基础教程(二)

    1.创建[服务中心],即 Eureka Server 1.1.新建 Spring Boot 工程,工程名称: springcloud-eureka-server 1.2.工程 pom.xml 文件添加 ...

  6. django项目用higcharts统计最近七天文章点击量。

    下载higcharts插件放在static文件夹下 前端引入 <script src="/static/highcharts/highcharts.js"></s ...

  7. C#程序保存dump文件

    作用 程序异常崩溃前使用此类为进程创建DUMP文件,之后可以使用WinDbg等工具进行分析. 辅助类代码 using System; using System.Diagnostics; using S ...

  8. BZOJ5509: [Tjoi2019]甲苯先生的滚榜

    题解 开n个平衡树对每个AC数维护罚时,然后不同AC数用树状数组维护即可. 其实挺好写的...就是评测的时候评的巨久... #include <bits/stdc++.h> using n ...

  9. eclipse 中的注释 快捷键 多行注释快捷键 单行注释快捷键

    Eclipse 中的两种注释方法: (1)多行注释(2)单行注释 一. 多行注释快捷键 1:添加注释Ctrl+Shift+/ :    添加/* */注释 示例:选中代码块后按下快捷键即可 /* fl ...

  10. SparkStreaming运行原理

    Spark Streaming应用也是Spark应用,Spark Streaming生成的DStream最终也是会转化成RDD,然后进行RDD的计算,所以Spark Streaming最终的计算是RD ...