京东评论情感分类器(基于bag-of-words模型)
京东评论情感分类器(基于bag-of-words模型)
近期在本来在研究paraVector模型,想拿bag-of-words来做对照。
数据集是京东的评论,经过人工挑选,选出一批正面和负面的评论。
实验的数据量不大,340条正面,314条负面。我一般拿200正面和200负面做训练,剩下做測试。
做着做着,领悟了一些机器学习的道理。发现,对于不同的数据集,效果是不同的。
对于特定的数据集,随便拿来一套模型可能并不适用。
对于这些评论,我感觉就是bag-of-words模型靠谱点。
由于这些评论的特点是语句简短,关键词重要。
paraVector模型感觉比較擅长长文本的分析,注重上下文。
事实上我还结合了两个模型来做一个新的模型,准确率有点提高,可是不大。可能我数据量太少了。
整理了一下思路,做了个评论情感分类的demo。
特征抽取是bag-of-words模型。
分类器是自己想的一个模型,结合了knn和kmeans的思想。依据对于正负样本的训练集分别求出两个聚类中心,每次新样本进来,跟两个中心做距离比較。
下面是demo的代码:
import java.util.Scanner;
public class BowInterTest {
public static void main(String[] args) throws Throwable
{
// TODO Auto-generated method stub
BowModel bm = new BowModel("/media/linger/G/sources/comment/test/all");//all=good+bad
double[][] good = bm.generateFeature("/media/linger/G/sources/comment/test/good",340);
double[][] bad = bm.generateFeature("/media/linger/G/sources/comment/test/bad",314);
bm.train(good,0,200,bad,0,200);//指定训练数据
//bm.test(good, 200, 340, bad, 200, 314);//指定測试数据
//交互模式
Scanner sc = new Scanner(System.in);
while(sc.hasNext())
{
String doc = sc.nextLine();
double[] fea = bm.docFea(doc);
Norm.arrayNorm2(fea);
double re = bm.predict(fea);
if(re<0)
{
System.out.println("good:"+re);
}
else
{
System.out.println("bad:"+re);
}
}
}
}
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.util.StringTokenizer; public class BowModel extends KnnCoreModel
{ Dict dict;
DocFeatureFactory dff; public BowModel(String path) throws IOException
{
dict = new Dict();
dict.loadFromLocalFile(path);
dff = new DocFeatureFactory(dict.getWord2Index());
} public double[] docFea(String doc)
{
return dff.getFeature(doc);
}
public double[][] generateFeature(String docsFile,int docNum) throws IOException
{
double[][] featureTable = new double[docNum][];
int docIndex=0;
File file = new File(docsFile);
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file),"utf-8"));
while(true)
{
String line=br.readLine();
if(line == null)
break;
featureTable[docIndex++] = dff.getFeature(line);
}
br.close();
return featureTable;
} }
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;
import java.util.Map.Entry; public class Dict
{
HashMap<String,Integer> word2Index =null;
Hashtable<String,Integer> word2Count = null;
void loadFromLocalFile(String path) throws IOException
{
word2Index = new HashMap<String,Integer>();
word2Count = new Hashtable<String,Integer>();
int index = 0;
File file = new File(path);
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file),"utf-8"));
while(true)
{
String line=br.readLine();
if(line == null)
break;
StringTokenizer tokenizer=new StringTokenizer(line," ");
while(tokenizer.hasMoreElements())
{
String term=tokenizer.nextToken();
if(word2Count.containsKey(term))
{ int freq=word2Count.get(term)+1;
word2Count.put(term, freq); }
else
{
word2Count.put(term, 1);
word2Index.put(term, index++);
}
}
}
br.close();
} public HashMap<String,Integer> getWord2Index()
{
return word2Index;
} public void print()
{
Iterator<Entry<String, Integer>> iter=word2Count.entrySet().iterator();
while(iter.hasNext())
{
Entry<String,Integer> item=(Entry<String,Integer>)iter.next();
if(item.getValue()>30)
System.out.printf("%s,%d\n",item.getKey(),item.getValue());
}
}
public static void main(String[] args) throws IOException
{
// TODO Auto-generated method stub
Dict dict = new Dict();
dict.loadFromLocalFile("/media/linger/G/sources/comment/test/all");
dict.print(); } }
import java.util.HashMap;
import java.util.StringTokenizer; public class DocFeatureFactory
{
HashMap<String,Integer> word2Index;
double[] feature;
int dim;
public DocFeatureFactory(HashMap<String,Integer> w2i)
{
word2Index = w2i;
dim = w2i.size();
} double[] getFeature(String doc)
{
feature = new double[dim];
int wordNum=0;
//while(wordNum<25)//这个作用跟规范化的一样啊
//{
StringTokenizer tokenizer=new StringTokenizer(doc," ");
while(tokenizer.hasMoreElements())
{
wordNum++;
String term =tokenizer.nextToken();
Integer index = word2Index.get(term);
if(index==null) continue;
feature[index]++;
}
//}
return feature;
} public static void main(String[] args)
{
// TODO Auto-generated method stub } }
public class KnnCoreModel
{
double[] good_standard ;
double[] bad_standard ;
public void train(double[][] good,int train_good_start,int train_good_end,
double[][] bad,int train_bad_start,int train_bad_end)
{
//double[][] good = generateFeature("/media/linger/G/sources/comment/test/good",340);
//double[][] bad = generateFeature("/media/linger/G/sources/comment/test/bad",314); //double[] arv = new double[good[0].length];
//double[] var = new double[good[0].length]; //2范式归一化
Norm.tableNorm2(good);
Norm.tableNorm2(bad);
good_standard = new double[good[0].length];
bad_standard = new double[bad[0].length];
for(int i=train_good_start;i<train_good_end;i++)
{
for(int j=0;j<good[i].length;j++)
{
good_standard[j]+=good[i][j];
}
} //System.out.println("\ngood core:");
for(int j=0;j<good_standard.length;j++)
{
good_standard[j]/=(train_good_end-train_good_start);
//System.out.printf("%f,",good_standard[j]); } for(int i=train_bad_start;i<train_bad_end;i++)
{
for(int j=0;j<bad[i].length;j++)
{
bad_standard[j]+=bad[i][j];
}
}
//System.out.println("\nbad core:");
for(int j=0;j<bad_standard.length;j++)
{
bad_standard[j]/=(train_bad_end-train_bad_start);
//System.out.printf("%f,",bad_standard[j]);
}
} public void test(double[][] good,int test_good_start,int test_good_end,
double[][] bad,int test_bad_start,int test_bad_end)
{
Norm.tableNorm2(good);
Norm.tableNorm2(bad);
int error=0;
double good_dis;
double bad_dis;
//test
for(int i=test_good_start;i<test_good_end;i++)
{
good_dis= distance(good[i],good_standard);
bad_dis = distance(good[i],bad_standard);
//good_dis= allDistance(good[i],good,train_good_start,train_good_end);
//bad_dis = allDistance(good[i],bad,train_bad_start,train_bad_end);
double dis= good_dis-bad_dis;
if(dis>0)
{
error++;
System.out.println("-:"+(dis));
}
else
{
System.out.println("+:"+(dis));
}
} for(int i=test_bad_start;i<test_bad_end;i++)
{
good_dis= distance(bad[i],good_standard);
bad_dis = distance(bad[i],bad_standard);
//good_dis= allDistance(bad[i],good,train_good_start,train_good_end);
//bad_dis = allDistance(bad[i],bad,train_bad_start,train_bad_end);
double dis= good_dis-bad_dis;
if(dis>0)
{ System.out.println("+:"+(dis));
}
else
{
error++;
System.out.println("-:"+(dis));
}
} int count = (test_good_end-test_good_start+test_bad_end-test_bad_start);
System.out.println("\nerror:"+error+",total:"+count);
System.out.println("error rate:"+(double)error/count);
System.out.println("acc rate:"+(double)(count-error)/count);
} public double predict(double[] fea)
{
double good_dis = distance(fea,good_standard);
double bad_dis = distance(fea,bad_standard);
return good_dis-bad_dis;
} private double distance(double[] src,double[] dst)
{
double sum=0;
if(src.length!=dst.length)
{
System.out.println("size not right!");
return sum;
}
for(int i=0;i<src.length;i++)
{
sum+=(dst[i]-src[i])*(dst[i]-src[i]);
}
//return Math.sqrt(sum);
return sum;
}
private double allDistance(double[]src,double[][] trainSet,int start,int end)
{
double sum=0;
for(int i=start;i<end && i<trainSet.length;i++)
{
sum+=distance(src,trainSet[i]);
}
return sum;
} }
public class Norm {
public static void arrayNorm2(double[] array)
{
double sum;
sum=0;
for(int j=0;j<array.length;j++)
{
sum +=array[j]*array[j];
}
if(sum == 0) return;
sum = Math.sqrt(sum);
for(int j=0;j<array.length;j++)
{
array[j]/=sum;
}
}
public static void tableNorm2(double[][] table)
{
double sum;
for(int i=0;i<table.length;i++)
{
sum=0;
for(int j=0;j<table[i].length;j++)
{
sum +=table[i][j]*table[i][j];
}
if(sum == 0) continue;
sum = Math.sqrt(sum);
for(int j=0;j<table[i].length;j++)
{
table[i][j]/=sum;
}
}
}
}
数据集下载:http://download.csdn.net/detail/linger2012liu/7758939
本文作者:linger
本文链接:http://blog.csdn.net/lingerlanlan/article/details/38418277
京东评论情感分类器(基于bag-of-words模型)的更多相关文章
- 【项目实战】Kaggle电影评论情感分析
前言 这几天持续摆烂了几天,原因是我自己对于Kaggle电影评论情感分析的这个赛题敲出来的代码无论如何没办法运行,其中数据变换的维度我无法把握好,所以总是在函数中传错数据.今天痛定思痛,重新写了一遍代 ...
- python爬虫——京东评论、jieba分词、wordcloud词云统计
接上一章,动态页面抓取——抓取京东评论区内容. url=‘https://club.jd.com/comment/productPageComments.action?callback=fetchJS ...
- .NET - 基于事件的异步模型
注:这是大概四年前写的文章了.而且我离开.net领域也有四年多了.本来不想再发表,但是这实际上是Active Object模式在.net中的一种重要实现方法,因此我把它掏出来发布一下.如果该模型有新的 ...
- 基于Pre-Train的CNN模型的图像分类实验
基于Pre-Train的CNN模型的图像分类实验 MatConvNet工具包提供了好几个在imageNet数据库上训练好的CNN模型,可以利用这个训练好的模型提取图像的特征.本文就利用其中的 “im ...
- word2vec 中的数学原理具体解释(五)基于 Negative Sampling 的模型
word2vec 是 Google 于 2013 年开源推出的一个用于获取 word vector 的工具包,它简单.高效,因此引起了非常多人的关注. 因为 word2vec 的作者 Tomas ...
- word2vec 中的数学原理具体解释(四)基于 Hierarchical Softmax 的模型
word2vec 是 Google 于 2013 年开源推出的一个用于获取 word vector 的工具包,它简单.高效,因此引起了非常多人的关注.因为 word2vec 的作者 Tomas M ...
- FaceRank-人脸打分基于 TensorFlow 的 CNN 模型
FaceRank-人脸打分基于 TensorFlow 的 CNN 模型 隐私 因为隐私问题,训练图片集并不提供,稍微可能会放一些卡通图片. 数据集 130张 128*128 张网络图片,图片名: 1- ...
- word2vec原理(二) 基于Hierarchical Softmax的模型
word2vec原理(一) CBOW与Skip-Gram模型基础 word2vec原理(二) 基于Hierarchical Softmax的模型 word2vec原理(三) 基于Negative Sa ...
- word2vec原理(三) 基于Negative Sampling的模型
word2vec原理(一) CBOW与Skip-Gram模型基础 word2vec原理(二) 基于Hierarchical Softmax的模型 word2vec原理(三) 基于Negative Sa ...
随机推荐
- win32 sdk树形控件的项拖拽实现
本课中,我们将学习如何使用树型视图控件.另外还要学习如何在树型视图中完成拖-拉动作,以及如何使用图象列表. 理论: 树型视图是一种特别的窗口,我们可以使用它一目了然地表示某种层次关系.譬如象在资源管理 ...
- POJ1422 最小路径覆盖入门
题意:DAG求最小路径覆盖. 注意:二分匹配只试用于求DAG的最小路径覆盖, 有环就不行,具体可以理解证明. 对n个点进行拆点,分成左右两排点,对于边<u, v> 建 <u', v ...
- MPICH3环境配置
最新版的mpich简化了运行方式,不再提供mpd开头的命令,只需要一个mpiexec即可启动mpi运行环境,方便了mpi编程.源代码下载地址:http://www.mpich.org/download ...
- Python之常用模块(待更新)
模块,用一砣代码实现了某个功能的代码集合. 类似于函数式编程和面向过程编程,函数式编程则完成一个功能,其他代码用来调用即可,提供了代码的重用性和代码间的耦合.而对于一个复杂的功能来,可能需要多个函数才 ...
- HDU 1007 近期点对
分治法求近期点对 递归将点不断分成小组.计算最短距离.此时的最短距离不过两点都属两块的某一块(这里的切割点是mid点). 还须要考虑两点分属两块的情况. 这时对于选点则把范围缩小到了以mid为中心. ...
- ios 正則表達式替换
1. 不可变字符串 (content 是不可变) NSRegularExpression *regularExpression = [NSRegularExpression regularExpr ...
- RGB與CIELAB色彩空間轉換
原地址:http://cg2010studio.wordpress.com/2012/10/02/rgb與cielab色彩空間轉換/ 之前有研究CIE L*a*b*色彩空間,現在想更進一步探討RGB色 ...
- linux内核笔记-内核同步
linux内核就相当于不断对请求进行响应的服务器,这些请求可能来自CPU,可能来自发出中断的外部设备.我们将内核看作两种请求的侍者. (1)老板提出请求,侍者如果空闲,为老板服务.(系统调用或异常) ...
- poj - 1170 - Shopping Offers(减少国家dp)
意甲冠军:b(0 <= b <= 5)商品的种类,每个人都有一个标签c(1 <= c <= 999),有需要购买若干k(1 <= k <=5),有一个单价p(1 & ...
- android
在特殊应用的特殊功能,以帮助通信系统的问题
在实际工程中的应用,进入一个特殊的应用后,系统的某个功能不能起作用. 当然,这个通信有非常多办法能够做到.笔者能够想到的至少有例如以下几种 1.利用property熟悉来实现,这种话须要添加一个特殊的 ...