京东评论情感分类器(基于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模型)的更多相关文章

  1. 【项目实战】Kaggle电影评论情感分析

    前言 这几天持续摆烂了几天,原因是我自己对于Kaggle电影评论情感分析的这个赛题敲出来的代码无论如何没办法运行,其中数据变换的维度我无法把握好,所以总是在函数中传错数据.今天痛定思痛,重新写了一遍代 ...

  2. python爬虫——京东评论、jieba分词、wordcloud词云统计

    接上一章,动态页面抓取——抓取京东评论区内容. url=‘https://club.jd.com/comment/productPageComments.action?callback=fetchJS ...

  3. .NET - 基于事件的异步模型

    注:这是大概四年前写的文章了.而且我离开.net领域也有四年多了.本来不想再发表,但是这实际上是Active Object模式在.net中的一种重要实现方法,因此我把它掏出来发布一下.如果该模型有新的 ...

  4. 基于Pre-Train的CNN模型的图像分类实验

    基于Pre-Train的CNN模型的图像分类实验  MatConvNet工具包提供了好几个在imageNet数据库上训练好的CNN模型,可以利用这个训练好的模型提取图像的特征.本文就利用其中的 “im ...

  5. word2vec 中的数学原理具体解释(五)基于 Negative Sampling 的模型

      word2vec 是 Google 于 2013 年开源推出的一个用于获取 word vector 的工具包,它简单.高效,因此引起了非常多人的关注. 因为 word2vec 的作者 Tomas ...

  6. word2vec 中的数学原理具体解释(四)基于 Hierarchical Softmax 的模型

      word2vec 是 Google 于 2013 年开源推出的一个用于获取 word vector 的工具包,它简单.高效,因此引起了非常多人的关注.因为 word2vec 的作者 Tomas M ...

  7. FaceRank-人脸打分基于 TensorFlow 的 CNN 模型

    FaceRank-人脸打分基于 TensorFlow 的 CNN 模型 隐私 因为隐私问题,训练图片集并不提供,稍微可能会放一些卡通图片. 数据集 130张 128*128 张网络图片,图片名: 1- ...

  8. word2vec原理(二) 基于Hierarchical Softmax的模型

    word2vec原理(一) CBOW与Skip-Gram模型基础 word2vec原理(二) 基于Hierarchical Softmax的模型 word2vec原理(三) 基于Negative Sa ...

  9. word2vec原理(三) 基于Negative Sampling的模型

    word2vec原理(一) CBOW与Skip-Gram模型基础 word2vec原理(二) 基于Hierarchical Softmax的模型 word2vec原理(三) 基于Negative Sa ...

随机推荐

  1. Android本地视频播放器开发--视频解码

    在上一章Android本地视频播放器开发--SDL编译编译中编译出sdl的支持库,当时我们使用的2.0,但是有些api被更改了,所以在以下的使用者中我们使用SDL1.3的库,这个库我会传上源码以及编译 ...

  2. android打包apk时混淆遇到的问题

    android打包apk的时候一般会选择混淆,而在eclipse中常使用的是proguard来混淆.有很多时候引用了第三方包的时候会导致打包不成功,或者打包成功不能运行的情况. 首先看看正常的prog ...

  3. C++历史

    C++历史 早期C++ •1979: 首次实现引入类的C(C with Classes first implemented) 1.新特性:类.成员函数.继承类.独立编译.公共和私有访问控制.友元.函数 ...

  4. Android服务之PackageManagerService启动源码分析

    了解了Android系统的启动过程的读者应该知道,Android的所有Java服务都是通过SystemServer进程启动的,并且驻留在SystemServer进程中.SystemServer进程在启 ...

  5. oracle rac 在完成安装错误。

    今天是2014.05.26,离别N继续使用长今博客.成交一直忙于最近.该条目加上家庭网络还没有缴纳会费,我开始变得不太安全.学习是一个需要冷静情绪.心脏的声音是. 由于改变笔记本,特别需要重新建立Ra ...

  6. [Word使用笔记]分类简介

    什么Vistual Studio , Eclipse , Xcode , 都弱爆了,Word比他们难多了 - -! 此分类用于记录Word的一些使用

  7. hdu1217Arbitrage--解题报告

    题意:套利,一个US币换取0.5 British pound,而1 British pound 换取10.0 French francs,同一时候 1 French franc buys 0.21 U ...

  8. Houdini Pyro流体的插值变速

    用简单的节点尝试了下Houdini流体的变速,这里的流体指的是Pyro,而不是FLIP.FLIP仅仅须要记录ID属性然后TimeBlend & TimeShift就可以. Vimeo 上图是一 ...

  9. Python批量删除指定目录下的指定类型的文件

    Python作为一种脚本语言.其很适合文件级的各种操作.以下的代码能够批量删除指定目录下的所有特定类型(CSV类型)的文件. import sys, csv , operator import os ...

  10. LLVM每日谈21 一些编译器和LLVM/Clang代码

    作者:闪亮宁(snsn1984) 一些自己的收藏LLVM/Clang代码,而他自己写一些一点点LLVM/Clang译器的代码.在这里把这些代码库分享出来,欢迎大家交流探讨. 1.crange http ...