京东评论情感分类器(基于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;
	}

}

本文作者:linger

本文链接:http://blog.csdn.net/lingerlanlan/article/details/38418277

京东评论情感分类器(基于bag-of-words模型),布布扣,bubuko.com

时间: 2024-10-01 04:04:19

京东评论情感分类器(基于bag-of-words模型)的相关文章

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

接上一章,抓取京东评论区内容. url='https://club.jd.com/comment/productPageComments.action?callback=fetchJSON_comment98vv399&productId=4560435&score=0&sortType=5&page=0&pageSize=10&isShadowSku=0&fold=1' 重点是productId--产品id.page--页码.pageSize:指定

用户评论情感极性判别

博客搬家:用户评论情感极性判别 本文章介绍百度点石平台上的一个训练赛的赛题代码,赛题是包括用户评论文字的情感判别的分类问题,赛题链接戳此处 数据预处理 使用测试数据和训练数据生成语料库 import numpy as np import jieba import codecs # 该函数作用是读取文件 def load_data(file_path): data_set = [] with open(file_path, 'r') as lines: for line in lines: lin

一种基于脑电图情感识别的新型深度学习模型

目录 本分享为脑机学习者Rose整理发表于公众号:脑机接口社区(微信号:Brain_Computer).QQ交流群:903290195 机器学习的最新进展使得检测和识别人类情绪的技术也得到了快速的发展.其中一部分机器学习技术中是通过分析脑电图(EEG)信号来工作的,这些信号本质上是对从一个人的头皮上收集的脑电活动的记录. 过去十多年来,大多数基于脑电图的情绪分类方法都采用了传统的机器学习方法,例如支持向量机(SVM)模型,因为这些方法需要的训练样本较少.事实上之所以使用需要训练样本量少的方法是因

基于RBM的判别模型/算法

参考论文: 1.A Practical Guide to Training Restricted Boltzmann Machines 2.Classification using Discriminative Restricted Boltzmann Machines 目前研究火热的深度学习中,RBM(限制玻尔兹曼机)是最为重要的一块奠基石.深度学习最为关键的预训练过程中,RBM是被当做生成模型来训练的.RBM能够很好的拟合数据的优点是其广泛应用于深度模型的关键,如果能够把RBM的这个优点应用

word2vec 中的数学原理详解(四)基于 Hierarchical Softmax 的模型

  word2vec 是 Google 于 2013 年开源推出的一个用于获取 word vector 的工具包,它简单.高效,因此引起了很多人的关注.由于 word2vec 的作者 Tomas Mikolov 在两篇相关的论文 [3,4] 中并没有谈及太多算法细节,因而在一定程度上增加了这个工具包的神秘感.一些按捺不住的人于是选择了通过解剖源代码的方式来一窥究竟,出于好奇,我也成为了他们中的一员.读完代码后,觉得收获颇多,整理成文,给有需要的朋友参考. 相关链接 (一)目录和前言 (二)预备知

基于SOA的编程模型

1.webservice是SOA架构的一种实现 ====================================================================================================== Spring-WS编程模型: 面向契约的开发:xml--对象(而不是对象---xml) 编程模型: 1.定义消息契约xml(数据契约+操作契约) 2.生成xsd 3.编写消息端点 4.配置序列化OXM 5.生成wsdl-操作契约 ========

基于tomcat响应处理模型实现的高并发web服务器

在上一篇博客中,一个简单的AIOweb处理例子,可以看到AIO异步处理,依赖操作系统完成IO操作的Proactor处理模型确实很强大,可以是实现高并发,高响应服务器的不错选择,但是在tomcat中的connector的处理模型还依旧是基于NIO的处理,当然,我认为这可能会在以后的版本进行改进,但另一方面,我更认为AIO的负载控制方面的处理可能是比较难的,因为AIO api并没有提供我们对分配线程组的处理,而只是提供一个线程组,交给操作系统去解决io处理上的问题,所以,这可能会给需要复杂处理的负载

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

  word2vec 是 Google 于 2013 年开源推出的一个用于获取 word vector 的工具包,它简单.高效,因此引起了非常多人的关注.因为 word2vec 的作者 Tomas Mikolov 在两篇相关的论文 [3,4] 中并没有谈及太多算法细节,因而在一定程度上添加了这个工具包的神奇感.一些按捺不住的人于是选择了通过解剖源码的方式来一窥到底,出于好奇,我也成为了他们中的一员.读完代码后.认为收获颇多.整理成文,给有须要的朋友參考. 相关链接 (一)文件夹和前言 (二)预备

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

基于Pre-Train的CNN模型的图像分类实验 MatConvNet工具包提供了好几个在imageNet数据库上训练好的CNN模型,可以利用这个训练好的模型提取图像的特征.本文就利用其中的 “imagenet-caffe-ref”的模型,提取图像特征(softmax前一层的输出,4096维),在几个常用的图像分类的数据库中进行了相应的分类实验.这实验的过程中,有对图片进行左右翻转用于增加训练数据.下面结果的表格中:Original原始结果,Flip增加翻转后的结果. 需要用到的toolbox及