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

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

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. 常用css属性拓展

    text-overflow:clip | ellipsis(默认值:clip)clip:当内联内容溢出块容器时,将溢出部分裁切掉.ellipsis:当内联内容溢出块容器时,将溢出部分替换为(...). ...

  2. 迅为电子4.3寸CAN总线工业平板电脑简介

    型号:iTOP-HMI043-C 4.3寸CAN总线工业平板电脑支持CAN通讯显示器,显示:显示尺寸:4.3英寸:分辨率:480×272 TFT液晶 65536色 :接口:支持CAN 2.0B:USB ...

  3. Leetcode_638.Shopping Offers

    https://leetcode.com/problems/shopping-offers/ In LeetCode Store, there are some kinds of items to s ...

  4. jQuery PC端图片预览,鼠标移上去查看大图

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  5. vue-cli 中使用less

    (1)安装Less模块: npm install less (2)安装less和less-loader,命令如下 npm install less less-loader --sava-dev (3) ...

  6. C++中const与constexpr区别

    对于对象来说 const指的是编译期常量和运行时常量,两者并没有区分 constexpr特指编译期常量 对于函数来说 const可以修饰类的成员函数,被修饰的函数在执行期间不会改变对象的值. clas ...

  7. JS判断滚动条是否停止滚动

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  8. STM32F407 跑马灯 库函数版 个人笔记

    原理图: MCU在开发板原理图的第二页,LED在开发板原理图的第三页 由图可知,PF9 ,PF10 若输出低电平则灯亮,高电平则灯灭 选推挽输出 代码步骤 使能IO口时钟. 调用函数RCC_AHB1P ...

  9. nativeLibraryDirectories=[/data/app/com.lukouapp-1/lib/arm64, /vendor/lib64, /system/lib64]]] couldn't find "libxxxx.so

    一开始我遇到的问题是,如果手机有SD卡槽,则不管有没有插卡,都会闪退,打日记后发现是找不到so文件.报错日记如下: nativeLibraryDirectories=[/data/app/com.lu ...

  10. SSM java.lang.NullPointerException

    如上图所示的异常 原来是少了这个东西,加上就好了