建立文本数据数学描写叙述的过程分为三个步骤:文本预处理、建立向量空间模型和优化文本向量。

文本预处理主要採用分词、停用词过滤等技术将原始的文本字符串转化为词条串或者特点的符号串。文本预处理之后,每个文本的词条串被进一步转换为一个文本向量,向量的每一维相应一个词条,其值反映的是这个词条与这个文本之间的类似度。类似度有非常多不同的计算方法。所以优化文本向量就是採用最为合适的计算方法来规范化文本向量,使其能更好地应用于文本分类和文本聚类等方面。

TFIDF算法

TF-IDF使得一个单词能尽量与文本在语义上相关。TF-IDF算法的实现步骤:



经过试验发现,用TFIDF/max(TFIDF)的方法效果是最好的。详细代码例如以下:

import java.io.File;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set; /**
* 经过试验发现,用TFIDF/max(TFIDF)的方法效果是最好的
* @author Angela
*/
public class TFIDF { private Map<String,Integer> TF;//文本词频集
private Map<String,Double> IDF;//特征-逆文档频率集 /**
* 构造方法,初始化TF和IDF
*/
public TFIDF(Map<String,Integer> TF,Map<String,Double> IDF){
this.TF=TF;
this.IDF=IDF;
} /**
* 计算文本特征集的tf-idf权值
* @return filePath文件的特征-TFIDF集
*/
public Map<String,Double> getTFIDF(){
Map<String,Double> tfidf=new HashMap<String,Double>();
for(Map.Entry<String,Integer> me: TF.entrySet()){
String f=me.getKey();
double weight=me.getValue()*IDF.get(f);
tfidf.put(f, weight);
}
return tfidf;
} /**
* 计算文本特征集的对数tf-idf权值
* @return filePath文件的特征-TFIDF集
*/
public Map<String,Double> getLogTFIDF(){
Map<String,Double> tfidf=new HashMap<String,Double>();
for(Map.Entry<String,Integer> me: TF.entrySet()){
String f=me.getKey();
double tf=1+Math.log(me.getValue());
double weight=tf*IDF.get(f);
tfidf.put(f, weight);
}
return tfidf;
} /**
* 进行规一化,每个特征除以这篇文本TFIDF值之和,构成新的TFIDF集
* @return filePath文件的特征-标准化TFIDF集
*/
public Map<String,Double> getNormalTFIDF(){
Map<String,Double> tfidf=new HashMap<String,Double>();
Map<String,Double> weight=getTFIDF();
double sum=MathUtil.calSum(weight);//计算TFIDF总和
for(Map.Entry<String, Double> me: weight.entrySet()){
String f=me.getKey();
double w=me.getValue()/sum;
tfidf.put(f, w);
}
return MapUtil.descend(tfidf);
} /**
* 进行标准化,每个特征除以这篇文本中最大的TFIDF值,构成新的TFIDF集
* @return filePath文件的特征-标准化TFIDF集
*/
public Map<String,Double> getStandardTFIDF(){
Map<String,Double> tfidf=new HashMap<String,Double>();
Map<String,Double> weight=getTFIDF();
Map<String,Double> temp=MapUtil.descend(weight);
Set<Map.Entry<String, Double>> set = temp.entrySet();
Iterator<Map.Entry<String,Double>> it = set.iterator();
double max=0;
if(it.hasNext()){
max=it.next().getValue();
}
for(Map.Entry<String, Double> me: weight.entrySet()){
String f=me.getKey();
double w=me.getValue()/max;
tfidf.put(f, w);
}
return MapUtil.descend(tfidf);
} /**
* 保存文本的TFIDF结果
* @param tf 文本的TF集
* @param idf IDF集
* @param savePath 保存路径
*/
public static void saveTFIDF(Map<String,Integer> tf,
Map<String,Double> idf,String savePath){
TFIDF tfidf=new TFIDF(tf,idf);
Map<String,Double> weight=tfidf.getStandardTFIDF();
Writer.saveMap(weight, savePath);
} /**
* 保存TFIDF结果
* @param filePath 文本集的TF集路径
* @param idfPath IDF路径
* @param tarPath 保存路径
*/
public static void saveTFIDF(String TFPath,String IDFPath,String tarPath){
File tar=new File(tarPath);
if(!tar.exists()) tar.mkdir();
Map<String,Double> idf=Reader.toDoubleMap(IDFPath);//IDF
File file=new File(TFPath);
File[] labels=file.listFiles();//类别
for(File label: labels){
String labelpath=tarPath+File.separator+label.getName();
File labelPath=new File(labelpath);
if(!labelPath.exists()) labelPath.mkdir();
File[] texts=label.listFiles();//文本
for(File text: texts){
String savePath=labelpath+File.separator+text.getName();
Map<String,Integer> tf=Reader.toIntMap(text.getAbsolutePath());
saveTFIDF(tf,idf,savePath);
System.out.println("Saved "+savePath);
}
}
} public static void main(String args[]){
String TFPath="data\\r8trainTF";
String IDFPath="data\\r8trainIDF.txt";
String tarPath="data\\r8trainTFIDF3";
saveTFIDF(TFPath,IDFPath,tarPath);
} }

向量空间模型VSM

余弦类似度

文本与文本之间的类似度不能简单地用欧式距离来计算。更合理的计算方式是余弦类似度。

以下就是涉及这两个知识点的工具类。

MathUtil存放通用的计算公式方法

import java.util.Map;

/**
*
* @author Angela
*/
public class MathUtil { /**
* 计算Map的键值之和
* @param map
* @return
*/
public static double calSum(Map<String,Double> map){
double sum=0;
for(Map.Entry<String,Double> me: map.entrySet()){
sum+=me.getValue();
}
return sum;
} /**
* 计算两篇文本的类似度
* @param text1 文本1
* @param text2 文本2
* @return text1和text2的余弦类似度。值越大越类似
*/
public static double calSim(Map<String,Double> text1,
Map<String,Double> text2){
double sim=0;//类似度
double sum=0;//同样特征的权重相乘之和
double len1=0;//文本1的长度
double len2=0;//文本2的长度
for(Map.Entry<String,Double> me: text1.entrySet()){
String f=me.getKey();
double value=me.getValue();
if(text2.containsKey(f)){
sum+=value*text2.get(f);
}
len1+=value*value;
}
for(Map.Entry<String,Double> me: text2.entrySet()){
double value=me.getValue();
len2+=value*value;
}
sim=sum/(Math.sqrt(len1)*Math.sqrt(len2));
return sim;
} }

GetData获取DF、TFIDF即VSM、类别成员clusterMember、类别列表LabelList及由TFIDF构造的其他数据

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set; /**
*
* @author Angela
*/
public class GetData { /**
* 依据TFIDF得到相应的DF集合
* 假设你的TFIDF集仅仅是原始的一部分,就用这种方法来获取相应的DF集
* @param tfidf TFIDF集合
* @return
*/
public static Map<String,Integer> getDF(Map<String,Map<String,Double>> tfidf){
Map<String,Integer> map=new HashMap<String,Integer>();
for(Map.Entry<String,Map<String,Double>> me: tfidf.entrySet()){
Map<String,Double> text=me.getValue();
for(Map.Entry<String,Double> t: text.entrySet()){
String feature=t.getKey();
if(map.containsKey(feature)){
map.put(feature,map.get(feature)+1);
}else{
map.put(feature, 1);
}
}
}
return map;
} /**
* 读取文本集,返回Map<类别+文件名称,Map<特征,权重>>
* 当你进行特征选择后,得到特征子集,能够用这种方法
* 从文本集中构建新的VSM
* @param filePath TFIDF存放路径
* @param featureSet 特征集
* @return
*/
public static Map<String,Map<String,Double>> getTFIDF(String filePath,
Set<String> featureSet){
Map<String,Map<String,Double>> map=new HashMap<String,Map<String,Double>>();
File path=new File(filePath);
File[] files=path.listFiles();//类别
for(File file: files){
String label=file.getName();
File[] texts=file.listFiles();//文本
for(File text: texts){
Map<String,Double> tfidf=Reader.toDoubleMap(text.getAbsolutePath());
Map<String,Double> temp=new HashMap<String,Double>();
for(Map.Entry<String,Double> me: tfidf.entrySet()){
String feature=me.getKey();
if(featureSet.contains(feature)){
temp.put(feature,me.getValue());
}
}
map.put(label+File.separator+text.getName(), temp);
}
}
return map;
} /**
* 依据特征集构建新的VSM,返回Map<类别+文件名称,Map<特征,权重>>
* 当你进行特征选择后,得到特征子集,能够用这种方法
* 从原始的VSM中构建新的VSM
* @param tfidf 原始的VSM
* @param featureSet 特征集
* @return
*/
public static Map<String,Map<String,Double>> getTFIDF(
Map<String,Map<String,Double>> tfidf,Set<String> featureSet){
Map<String,Map<String,Double>> map=new HashMap<String,Map<String,Double>>();
for(Map.Entry<String,Map<String,Double>> me: tfidf.entrySet()){
Map<String,Double> text=me.getValue();
Map<String,Double> temp=new HashMap<String,Double>();
for(Map.Entry<String,Double> t: text.entrySet()){
String feature=t.getKey();
if(featureSet.contains(feature)){
temp.put(feature,t.getValue());
}
}
map.put(me.getKey(), temp);
}
return map;
} /**
* 依据TFIDF文本集和特征集构建
* Map<特征,Map<文本路径名,特征在该文本中的TFIDF值>>
* @param tfidf TFIDF文本集
* @param featureSet 特征集
* @return
*/
public static Map<String,Map<String,Double>> getTermIndex(
Map<String,Map<String,Double>> tfidf,Set<String> featureSet){
Map<String,Map<String,Double>> termIndex=
new HashMap<String,Map<String,Double>>();
for(String f: featureSet){//特征
//包括有特征f的全部文本及特征f在该文本中的权重
Map<String,Double> feature=new HashMap<String,Double>();
for(Map.Entry<String,Map<String,Double>> me: tfidf.entrySet()){
Map<String,Double> text=me.getValue();//文本
if(text.containsKey(f)){//假设文本包括特征f
//将文本的路径和特征f的值赋给feature
feature.put(me.getKey(), text.get(f));
}
}
//将特征及feature赋给termIndex
termIndex.put(f,feature);
}
return termIndex;
} /**
* 依据文本特征集和特征集构建Map<特征,Set<文本路径名>>
* @param dataSet Map<文本,Set<特征>>
* @param featureSet 特征集
* @return
*/
public static Map<String,Set<String>> getFeatureIndex(
Map<String,Set<String>> dataSet,Set<String> featureSet){
Map<String,Set<String>> featureIndex=
new HashMap<String,Set<String>>();
for(String f: featureSet){//特征
Set<String> textSet=new HashSet<String>();
for(Map.Entry<String,Set<String>> me: dataSet.entrySet()){
String textPath=me.getKey();//文本路径
Set<String> feature=me.getValue();//文本的特征集
//假设文本包括特征f
if(feature.contains(f)){
textSet.add(textPath);
}
}
//将特征及文本集赋给termText
featureIndex.put(f,textSet);
}
return featureIndex;
} /**
* 文本集的类别成员
* @param filePath
* @return
*/
public static Map<Integer,List<String>> getClusterMember(String filePath){
Map<Integer,List<String>> clusterMember=new HashMap<Integer,List<String>>();
File file=new File(filePath);
File[] labels=file.listFiles();
int labelNum=labels.length;
for(int i=0;i<labelNum;i++){
File[] texts=labels[i].listFiles();
String label=labels[i].getName();
List<String> member=new ArrayList<String>();
for(File text: texts){
member.add(label+File.separator+text.getName());
}
clusterMember.put(i, member);
}
return clusterMember;
} /**
* 类别集
* @param filePath
* @return
*/
public static List<String> getLabelList(String filePath){
List<String> labelList=new ArrayList<String>();
File files=new File(filePath);
File[] file=files.listFiles();
for(File f: file){
labelList.add(f.getName());
}
return labelList;
} /**
* 依据TFIDF集构造类别集
* @param TFIDF
* @return
*/
public static List<String> getLabelList(Map<String,Map<String,Double>> TFIDF){
Set<String> labels=new HashSet<String>();
for(Map.Entry<String,Map<String,Double>> me: TFIDF.entrySet()){
String path=me.getKey();
String label=path.substring(0,path.lastIndexOf(File.separator));
labels.add(label);
}
List<String> labelList=new ArrayList<String>(labels);
return labelList;
} }

由于文本数据量一般非常大,并且VSM具有高维稀疏的特点。所以一般须要进行特征选择。来降低特征的数量。

下一节,我将介绍几种特征选择方法。

(6)文本挖掘(三)——文本特征TFIDF权重计算及文本向量空间VSM表示的更多相关文章

  1. 文本情感分析(一):基于词袋模型(VSM、LSA、n-gram)的文本表示

    现在自然语言处理用深度学习做的比较多,我还没试过用传统的监督学习方法做分类器,比如SVM.Xgboost.随机森林,来训练模型.因此,用Kaggle上经典的电影评论情感分析题,来学习如何用传统机器学习 ...

  2. 文本分类学习(三) 特征权重(TF/IDF)和特征提取

    上一篇中,主要说的就是词袋模型.回顾一下,在进行文本分类之前,我们需要把待分类文本先用词袋模型进行文本表示.首先是将训练集中的所有单词经过去停用词之后组合成一个词袋,或者叫做字典,实际上一个维度很大的 ...

  3. 经典文本特征表示方法: TF-IDF

    引言 在信息检索, 文本挖掘和自然语言处理领域, IF-IDF 这个名字, 从它在 20 世纪 70 年代初被发明, 已名震江湖近半个世纪而不曾衰歇. 它表示的简单性, 应用的有效性, 使得它成为不同 ...

  4. tf-idf 词条权重计算

    在文本分类问题中,某些高频词一直出现,这样的词对区分文档的作用不大,例如: D1:  'Job was the chairman of Apple Inc.' D2:  'I like to use ...

  5. 关键词权重计算算法:TF-IDF

    TF-IDF(Term Frequency–Inverse Document Frequency)是一种用于资讯检索与文本挖掘的常用加权技术.TF-IDF是一种统计方法,用以评估一字词对于一个文件集或 ...

  6. sklearn之特征提取(文本特征)

    1.引言 关于文本的提取有很多方法,本文主要探索下sklearn官方的文本特征提取功能. 2.文本特征提取 文本分析是机器学习算法的主要应用领域. 然而,原始数据,符号文字序列不能直接传递给算法,因为 ...

  7. 机器学习入门-文本特征-使用LDA主题模型构造标签 1.LatentDirichletAllocation(LDA用于构建主题模型) 2.LDA.components(输出各个词向量的权重值)

    函数说明 1.LDA(n_topics, max_iters, random_state)  用于构建LDA主题模型,将文本分成不同的主题 参数说明:n_topics 表示分为多少个主题, max_i ...

  8. 前端极易被误导的css选择器权重计算及css内联样式的妙用技巧

    记得大学时候,专业课的网页设计书籍里面讲过css选择器权重的计算:id是100,class是10,html标签是5等等,然后全部加起来的和进行比较... 我只想说:真是误人子弟,害人不浅! 最近,在前 ...

  9. CSS 选择器权重计算规则

    其实,CSS有自己的优先级计算公式,而不仅仅是行间>内部>外部样式:ID>class>元素. 一.样式类型 1.行间 <h1 style="font-size: ...

随机推荐

  1. 前端Unicode转码的好处

    站长工具支持Unicode转码:http://tool.chinaz.com/Tools/Unicode.aspx (这是一个网页标题)转码后 ------>变为:\u8fd9\u662f\u4 ...

  2. leetcode_357. Count Numbers with Unique Digits

    https://leetcode.com/problems/count-numbers-with-unique-digits/ 给定一个n,计算[0,10^n]中十进制中每一位都不相同的数的数目. c ...

  3. 解决vue项目eslint校验 Do not use 'new' for side effects 的两种方法

    import Vue from 'vue' import App from './App.vue' import router from './router' new Vue({ el: '#app' ...

  4. Leetcode 54:Spiral Matrix 螺旋矩阵

    54:Spiral Matrix 螺旋矩阵 Given a matrix of m x n elements (m rows, n columns), return all elements of t ...

  5. C#语言中循环分类总结

    C#语言中,循环主要分为4种,分别是:while循环.do while循环.for循环.foeach循环.下面我将分类对循环语句总结. 1.while循环: 如果循环条件为真,则执行循环体:执行完循环 ...

  6. 全国高校绿色计算大赛 预赛第一阶段(Python)

    第1关将字符串反转 #!/usr/bin/env python # -*- coding: utf-8 -*- class Task: def inversion(self, str): # **** ...

  7. BZOJ 4464 旅行时的困惑 最小流

    题面: Waldives 有 N 个小岛.目前的交通系统中包含 N-1 条快艇专线,每条快艇 专线连接两个岛.这 N-1条快艇专线恰好形成了一棵树. 由于特殊的原因,所有N-1条快艇专线都是单向的.这 ...

  8. 笔试算法题(01):字符串倒置 & 八皇后问题

    出题:将字符串“ABCD1234efgh”进行前后对调: 分析: 常见的考查指针使用的案例,知道字符串长度之后,依次交换位置i以及位置(length-1-i)上的内容,直到重叠: 注意不能直接修改指针 ...

  9. Python re模块 subprocess模块

    re模块 内部实现不是Python 而是调用了c的库 re是什么 正则 表达 式子 就是一些带有特殊含义的符号或者符号的组合作用: 对字符串进行过滤 在一对字符串中找到所关心的内容 你就需要告诉计算机 ...

  10. MongoDB安装与配置启动

    1.下载安装包.mongodb-linux-x86_64-rhel62-3.6.3.tgz 2.解压.修改名字. 3.修改配置文件: # mongodb.conf #where to loglogpa ...