# -*- coding: utf-8 -*-
"""
Created on Tue Jul 31 15:09:58 2018

@author: Administrator
"""

'''
从字典类型加载特征
类 DictVectorizer 可用于将标准的Python字典(dict)对象列表的要素数组转换为 scikit-learn 估计器使用的 NumPy/SciPy 表示形式。
'''

from sklearn.feature_extraction import DictVectorizer

measurements = [
            {'name':'student1','age':12},
            {'boy':True,'parent':'baba'},
            {'size':16},
        ]

vec = DictVectorizer().fit(measurements)  # 定义一个加载器,后对一个字典对象提取特征。
print('提取的特征:',vec.get_feature_names())  # 查看提取的新属性
print('稀疏矩阵形式:\n',vec.transform(measurements))
print('二维矩阵形式:\n',vec.transform(measurements).toarray())
# In[1]
'''
文本特征提取
类 CountVectorizer 在单个类中实现了 tokenization (词语切分)和 occurrence counting (出现频数统计):
'''

from sklearn.feature_extraction.text import CountVectorizer
corpus = ['This is the first document.',
          'This is the second second document.',
          'And the third one.',
          'Is this the first document?',]

vectorizer = CountVectorizer()
X = vectorizer.fit_transform(corpus)  # 默认提取至少 包含2个字母的单词
print('所有特征:',vectorizer.get_feature_names())
print('样本特征向量:\n',X.toarray())   # X本身为稀疏矩阵存储形式,toarray转换为二维矩阵形式

print('document属性的列索引:',vectorizer.vocabulary_.get('document'))  # 从 特征 名称到矩阵的(列索引)

# 提取一个单词或两个单词形成的词组。这样就能识别“is this”和“this is”这两种词汇了
bigram_vectorizer = CountVectorizer(ngram_range=(1, 2),token_pattern=r'\b\w+\b', min_df=1)
analyze = bigram_vectorizer.build_analyzer()
print('所有分词:',analyze('Bi-grams are cool!'))
# In[2]
'''
Tf–idf 项加权

在一个大的文本语料库中,一些单词将出现很多次(例如 “the”, “a”, “is” 是英文),因此对文档的实际内容没有什么有意义的信息。 如果我们将直接计数数据直接提供给分类器,那么这些频繁词组会掩盖住那些我们关注但很少出现的词。

为了为了重新计算特征权重,并将其转化为适合分类器使用的浮点值,因此使用 tf-idf 变换是非常常见的。

Tf表示术语频率,而 tf-idf 表示术语频率乘以转制文档频率: tf-idf(t,d)=tf(t,d)×idf(t).tf-idf(t,d)=tf(t,d)×idf(t).
使用 TfidfTransformer 的默认设置,TfidfTransformer(norm='l2', use_idf=True, smooth_idf=True, sublinear_tf=False) 术语频率,一个术语在给定文档中出现的次数乘以 idf 组件, 计算为

idf(t)=log1+nd1+df(d,t)+1,idf(t)=log1+nd1+df(d,t)+1,
其中 n_d 是文档的总数,df(d,t)df(d,t) 是包含术语 t 的文档数。 然后,所得到的 tf-idf 向量通过欧几里得范数归一化:

vnorm=v||v||2=vv12+v22+⋯+vn2√.vnorm=v||v||2=vv12+v22+⋯+vn2.
它源于一个词权重的信息检索方式(作为搜索引擎结果的评级函数),同时也在文档分类和聚类中表现良好。

以下部分包含进一步说明和示例,说明如何精确计算 tf-idfs 以及如何在 scikit-learn 中计算 tf-idfs, TfidfTransformer 并 TfidfVectorizer 与定义 idf 的标准教科书符号略有不同

idf(t)=lognd1+df(d,t).idf(t)=lognd1+df(d,t).
在 TfidfTransformer 和 TfidfVectorizer 中 smooth_idf=False,将 “1” 计数添加到 idf 而不是 idf 的分母:

idf(t)=lognddf(d,t)+1
'''

from sklearn.feature_extraction.text import TfidfTransformer
transformer = TfidfTransformer(smooth_idf=False)  # smooth_idf=False,将 “1” 计数添加到 idf 而不是 idf 的分母
# transformer = TfidfTransformer()
# 第一个特征经常出现,所以作用不大,第二个特征和第三个特征不经常出现,所以比较重要
counts = [[3, 0, 1],
          [2, 0, 0],
          [3, 0, 0],
          [4, 0, 0],
          [3, 2, 0],
          [3, 0, 2]]
tfidf = transformer.fit_transform(counts)
print('稀疏矩阵存储:\n',tfidf)
print('二维矩阵存储:\n',tfidf.toarray())
print('特征权重:',transformer.idf_)
# In[3]