使用Spark MLlib进行情感分析

使用Spark MLlib进行情感分析

使用Spark MLlib进行情感分析

一、实验说明

在当今这个互联网时代,人们对于各种事情的舆论观点都散布在各种社交网络平台或新闻提要中。我们可以在移动设备或是个人PC上轻松地发布自己的观点。对于这种网上海量分布地数据,我们可以利用文本分析来挖掘各种观点。如下图中,CognoviLabs利用Twitter上人们发布对于美国大选两个候选人的推特,进行情感分析的结果。从这张图我们也可以直观地感受到民意所向(此图发表日期为10月10日,早于今年美国大选的日子)。

图片来源:CognoviLabs / Twitris

本次课程,我们将利用推特上的数据结合Spark MLlib实现人们对美国这两位总统的情感分析,查看在美国不同地方的网民们对于他们的看法如何。

1.1 知识点

  • Twitter数据
  • Spark MLlib情感分析
  • Python 地图可视化工具Basemap

1.2 实验流程

  1. 获取twitter流数据
  2. tweet数据进行情感分析
  3. 分析结果可视化

二、Twitter流数据

Twitter Streaming API为开发者提供了可用于获得推特上数据的开发者接口。大家可根据Twitter Scrape中的操作获取Twitter中有关Trump和Hillary的推特数据。

由于对Twitter的操作需要FQ,为方便大家进行后续实验操作,我们已将数据保存至tweets.jsondonald.jsonhillary.json中,json 文件地址将在后续实验操作时给出。tweets.json包括和川普及希拉里有关的推特,而donald.json和hillary.json仅包括其文件名代表的候选人有关推特。

使用Tweepy接口获得的推特中包含很多数据,但由于我们只关心其发表内容的情感属性值,因此我们仅保存了其中的推特内容,及发表推特用户所在地。 我们所使用的Twitter数据内容:

数据名 数据描述
polarity 该twitter的情感属性值(0:积极,1:无感,2:消极)
text 推特内容
user_localtion 用户所在地区

其中polarity的内容由python自然语言处理包 TextBlob获得,这里我们对textblob返回的polarity进行了特殊处理,设置polarity>0时为积极情感(polarity=0),polarity=0时为无感(polarity=1),polarity<0时为消极情绪(polarity=2)

三、Spark MLLib进行情感分析

3.1环境配置

Apach Spark的Python接口pyspark安装:

#安装pyspark
$ wget http://labfile.oss.aliyuncs.com/courses/722/spark-2.0.2-bin-hadoop2.7.tgz
$ tar zxvf spark-2.0.2-bin-hadoop2.7.tgz
$ sudo mv spark-2.0.2-bin-hadoop2.7 /usr/bin/spark-2.0.2

进入目录/usr/bin/spark-2.0.2/conf中设置配置文件spark-env.sh

$ cd /usr/bin/spark-2.0.2/conf

# 使用模板文件复制一份配置文件进行设置
$ sudo cp spark-env.sh.template spark-env.sh
$ vim spark-env.sh #编辑spark-env.sh,所使用的编辑器可根据个人爱好

# 使用vim或gedit编辑文件spark-env.sh
# 添加以下内容设置spark的环境变量
export SPARK_HOME=/usr/bin/spark-2.0.2

安装python相关的包:

wget http://labfile.oss.aliyuncs.com/courses/722/numpy-1.11.3-cp27-cp27mu-manylinux1_x86_64.whl
wget http://labfile.oss.aliyuncs.com/courses/722/pyparsing-2.1.10-py2.py3-none-any.whl
wget http://labfile.oss.aliyuncs.com/courses/722/pytz-2016.10-py2.py3-none-any.whl
wget http://labfile.oss.aliyuncs.com/courses/722/cycler-0.10.0-py2.py3-none-any.whl
wget http://labfile.oss.aliyuncs.com/courses/722/python_dateutil-2.6.0-py2.py3-none-any.whl
wget http://labfile.oss.aliyuncs.com/courses/722/matplotlib-1.5.3-cp27-cp27mu-manylinux1_x86_64.whl

sudo pip install numpy-1.11.3-cp27-cp27mu-manylinux1_x86_64.whl
sudo pip install pyparsing-2.1.10-py2.py3-none-any.whl
sudo pip install pytz-2016.10-py2.py3-none-any.whl
sudo pip install cycler-0.10.0-py2.py3-none-any.whl
sudo pip install python_dateutil-2.6.0-py2.py3-none-any.whl
sudo pip install matplotlib-1.5.3-cp27-cp27mu-manylinux1_x86_64.whl

可视化分析结果使用的是python的地图可视化第三方包Basemap,basemap是Python中一个可用于地理信息可视化的包,安装basemap过程如下:

$ wget http://labfile.oss.aliyuncs.com/courses/722/basemap-1.0.7.tar.gz
$ tar zxvf basemap-1.0.7.tar.gz
$ cd basemap-1.0.7
$ cd geos-3.3.3
$ ./configure
$ make
$ sudo make install

上述过程需等待一段比较漫长的时间,这期间可以先浏览后续实验步骤。当执行完毕后返回目录basemap-1.0.7并安装basemap

$ cd ..
# 先更新依赖包,再进行安装
$ sudo apt-get build-dep python-lxml
$ sudo python setup.py install

# 安装后更新,并安装python-tk
$ sudo apt-get update
$ sudo apt-get install python-tk

进入examples目录运行程序simplestest.py查看是否安装成功

$ cd examples
$ python simpletest.py

3.2 实验操作

进入Code目录中并创建 shiyanlou_cs722 目录,通过以下命令获得tweets.jsondonald.jsonhillary.json文件。

$ wget http://labfile.oss.aliyuncs.com/courses/722/tweets.json
$ wget http://labfile.oss.aliyuncs.com/courses/722/donald.json
$ wget http://labfile.oss.aliyuncs.com/courses/722/hillary.json

创建sparkSA.py文件开始我们的实验。

注意: 本次实验操作的所有文件及代码都应存放在同一个目录——shiyanlou_cs722下。

导入相关模块

# -*- coding=utf8 -*-
from __future__ import print_function
import json
import re
import string
import numpy as np

from pyspark import SparkContext, SparkConf
from pyspark import SQLContext
from pyspark.mllib.classification import NaiveBayes
from pyspark.mllib.tree import RandomForest
from pyspark.mllib.feature import Normalizer
from pyspark.mllib.regression import LabeledPoint

使用Spark前的准备,因为实验楼有spark相关课程,这里就不做过多介绍

conf = SparkConf().setAppName("sentiment_analysis")
sc = SparkContext(conf=conf)
sc.setLogLevel("WARN")
sqlContext = SQLContext(sc)

进行情感分析的处理步骤如下图所示:

实验中我们利用获得的 tweets.json 作为情感分析分类器模型的训练集,这里测试集是用hillary.json,想要分析川普的,只需将测试集对应换成donald.json即可

据图可知,我们首先将每一条的推特数据分词,由于这里分析的是英文的tweet推特内容,因此只需将每个单词分开即可(与中文情感分析的不同),并定义stop_words 停用词一些无关情感分析的词

#寻找推文的协调性
#符号化推文的文本
#删除停用词,标点符号,url等
remove_spl_char_regex = re.compile(‘[%s]‘ % re.escape(string.punctuation))  # regex to remove special characters
stopwords = [u‘rt‘, u‘re‘, u‘i‘, u‘me‘, u‘my‘, u‘myself‘, u‘we‘, u‘our‘,               u‘ours‘, u‘ourselves‘, u‘you‘, u‘your‘,
             u‘yours‘, u‘yourself‘, u‘yourselves‘, u‘he‘, u‘him‘, u‘his‘, u‘himself‘, u‘she‘, u‘her‘, u‘hers‘,
             u‘herself‘, u‘it‘, u‘its‘, u‘itself‘, u‘they‘, u‘them‘, u‘their‘, u‘theirs‘, u‘themselves‘, u‘what‘,
             u‘which‘, u‘who‘, u‘whom‘, u‘this‘, u‘that‘, u‘these‘, u‘those‘, u‘am‘, u‘is‘, u‘are‘, u‘was‘, u‘were‘,
             u‘be‘, u‘been‘, u‘being‘, u‘have‘, u‘has‘, u‘had‘, u‘having‘, u‘do‘, u‘does‘, u‘did‘, u‘doing‘, u‘a‘,
             u‘an‘, u‘the‘, u‘and‘, u‘but‘, u‘if‘, u‘or‘, u‘because‘, u‘as‘, u‘until‘, u‘while‘, u‘of‘, u‘at‘, u‘by‘,
             u‘for‘, u‘with‘, u‘about‘, u‘against‘, u‘between‘, u‘into‘, u‘through‘, u‘during‘, u‘before‘, u‘after‘,
             u‘above‘, u‘below‘, u‘to‘, u‘from‘, u‘up‘, u‘down‘, u‘in‘, u‘out‘, u‘on‘, u‘off‘, u‘over‘, u‘under‘,
             u‘again‘, u‘further‘, u‘then‘, u‘once‘, u‘here‘, u‘there‘, u‘when‘, u‘where‘, u‘why‘, u‘how‘, u‘all‘,
             u‘any‘, u‘both‘, u‘each‘, u‘few‘, u‘more‘, u‘most‘, u‘other‘, u‘some‘, u‘such‘, u‘no‘, u‘nor‘, u‘not‘,
             u‘only‘, u‘own‘, u‘same‘, u‘so‘, u‘than‘, u‘too‘, u‘very‘, u‘s‘, u‘t‘, u‘can‘, u‘will‘, u‘just‘, u‘don‘,
             u‘should‘, u‘now‘]

# tokenize函数对tweets内容进行分词
def tokenize(text):
    tokens = []
    text = text.encode(‘ascii‘, ‘ignore‘)  # to decode
    text = re.sub(‘http[s]?://(?:[a-zA-Z]|[0-9]|[[email protected]&+]|[!*(),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+‘, ‘‘,
                  text)  # to replace url with ‘‘
    text = remove_spl_char_regex.sub(" ", text)  # Remove special characters
    text = text.lower()

    for word in text.split():
        if word not in stopwords                 and word not in string.punctuation                 and len(word) > 1                 and word != ‘``‘:
            tokens.append(word)
    return tokens

Spark MLlib中提供的机器学习模型处理的是向量形式的数据,因此我们需将文本转换为向量形式,为了节省时间,这里我们利用Spark提供的Word2Vec功能结合其提供的text8文件中的一部分单词进行了word2vec模型的预训练,并将模型保存至word2vecM_simple文件夹中,因此本次实验中将tweets转换为向量时直接调用此模型即可,从以下地址中获得此离线模型并解压:

cd ~
wget http://labfile.oss.aliyuncs.com/courses/722/word2vecM_simple.zip
unzip word2vecM_simple.zip

由于实验楼的在线环境限制,同学们可线下使用text8自行训练词向量转换模型,或线上搜索利用tweets进行分词训练的word2vec模型

定义分词文本转换为向量的函数

def doc2vec(document):
    # 100维的向量
    doc_vec = np.zeros(100)
    tot_words = 0

    for word in document:
        try:
        # 查找该词在预训练的word2vec模型中的特征值
            vec = np.array(lookup_bd.value.get(word)) + 1
            # print(vec)
            # 若该特征词在预先训练好的模型中,则添加到向量中
            if vec != None:
                doc_vec += vec
                tot_words += 1
        except:
            continue

    vec = doc_vec / float(tot_words)
    return vec

读入预先训练好的文本向量化模型word2vecM

lookup = sqlContext.read.parquet("/home/shiyanlou/word2vecM_simple/data").alias("lookup")
lookup.printSchema()
lookup_bd = sc.broadcast(lookup.rdd.collectAsMap())

情感分析相关的函数定义好后,我们便可从json文件中读入数据,创建RDD对象,利用spark mllib的分类器进行情感分析:

# 读入tweets.json作为分类器训练数据集
with open(‘tweets.json‘, ‘r‘) as f:
    rawTrn_data = json.load(f)
    f.close()

trn_data = []
for obj in rawTrn_data[‘results‘]:
    token_text = tokenize(obj[‘text‘]) # 规范化推特文本,进行分词
    tweet_text = doc2vec(token_text) # 将文本转换为向量
    # 使用LabeledPoint 将文本对应的情感属性polariy:该条训练数据的标记label,tweet_text:训练分类器的features特征,结合成可作为spark mllib分类训练的数据类型
    trn_data.append(LabeledPoint(obj[‘polarity‘], tweet_text)) 

trnData = sc.parallelize(trn_data)
#print(trnData)
print("------------------------------------------------------")

# 读入hillary.json作为分类器测试数据集
with open(‘hillary.json‘, ‘r‘) as f:
    rawTst_data = json.load(f)
    f.close()

tst_data = []
for obj in rawTst_data[‘results‘]:
    token_text = tokenize(obj[‘text‘])
    tweet_text = doc2vec(token_text)
    tst_data.append(LabeledPoint(obj[‘polarity‘], tweet_text))

tst_dataRDD = sc.parallelize(tst_data)

# 训练随机森林分类器模型
model = RandomForest.trainClassifier(trnData, numClasses=3, categoricalFeaturesInfo={},
                                     numTrees=3, featureSubsetStrategy="auto",
                                     impurity=‘gini‘, maxDepth=4, maxBins=32)

# 利用训练好的模型进行模型性能测试
predictions = model.predict(tst_dataRDD.map(lambda x: x.features))
labelsAndPredictions = tst_dataRDD.map(lambda lp: lp.label).zip(predictions)
# 计算分类错误率
testErr = labelsAndPredictions.filter(lambda (v, p): v != p).count() / float(tst_dataRDD.count())
print(‘Test Error = ‘ + str(testErr))
print(‘Learned classification tree model:‘)
# 输出训练好的随机森林的分类决策模型
print(model.toDebugString())

在编写完代码后,在shiyanlou_cs722目录下,通过spark-submit命令提交程序运行:

$ /usr/bin/spark-2.0.2/bin/spark-submit --master=local sparkSA.py
 --master=local sparkSA.py

在下一节的可视化的函数编写后,也是通过此命令提交运行程序。

训练得到的随机森林模型:

四、分析结果可视化

基于上一小节的RandomForest随机森林的训练结果,我们利用该分类器对推特上关于hillary的情感分析结果,结合basemap将其展示到美国的48个州(除去阿拉斯加及夏威夷)上,观察这48个州对于 hillary 的看法。

我们将在函数res_visulization中绘制可视化结果,首先我们需要定义该函数。

导入作图相关模块。

from mpl_toolkits.basemap import Basemap
from mpl_toolkits.basemap import cm
import matplotlib.pyplot as plt
import matplotlib as mpl
from matplotlib.colors import rgb2hex
from matplotlib.patches import Polygon

我们本次通过美国的shapefile结合basemap进行绘图,因此需要以下三个文件(这个三个文件需放置在目录shiyanlou_cs722下):

wget http://labfile.oss.aliyuncs.com/courses/722/st99_d00.shp
wget http://labfile.oss.aliyuncs.com/courses/722/st99_d00.dbf
wget http://labfile.oss.aliyuncs.com/courses/722/st99_d00.shx

函数res_visulization可视化情感分析结果

# pred_result:利用spark mllib 情感分析结果
def res_visulization(pred_result):
    # popdensity_ori 用于保存基于我们事先给定的推特情感极性,不同州的情感属性
    popdensity_ori = {‘New Jersey‘:  0., ‘Rhode Island‘: 0., ‘Massachusetts‘: 0., ‘Connecticut‘: 0.,
                      ‘Maryland‘: 0.,‘New York‘: 0., ‘Delaware‘: 0., ‘Florida‘: 0., ‘Ohio‘: 0., ‘Pennsylvania‘: 0.,
                      ‘Illinois‘: 0., ‘California‘: 0., ‘Hawaii‘: 0., ‘Virginia‘: 0., ‘Michigan‘:    0.,
                      ‘Indiana‘: 0., ‘North Carolina‘: 0., ‘Georgia‘: 0., ‘Tennessee‘: 0., ‘New Hampshire‘: 0.,
                      ‘South Carolina‘: 0., ‘Louisiana‘: 0., ‘Kentucky‘: 0., ‘Wisconsin‘: 0., ‘Washington‘: 0.,
                      ‘Alabama‘:  0., ‘Missouri‘: 0., ‘Texas‘: 0., ‘West Virginia‘: 0., ‘Vermont‘: 0.,
                      ‘Minnesota‘:  0., ‘Mississippi‘: 0., ‘Iowa‘: 0., ‘Arkansas‘: 0., ‘Oklahoma‘: 0.,
                      ‘Arizona‘: 0., ‘Colorado‘: 0., ‘Maine‘: 0., ‘Oregon‘: 0., ‘Kansas‘: 0., ‘Utah‘: 0.,
                      ‘Nebraska‘: 0., ‘Nevada‘: 0., ‘Idaho‘: 0., ‘New Mexico‘:  0., ‘South Dakota‘:    0.,
                      ‘North Dakota‘: 0., ‘Montana‘: 0., ‘Wyoming‘: 0., ‘Alaska‘: 0.}
    # popdensity 用于保存基于随机森林分析的推特情感极性,不同州的情感属性
    popdensity  = {‘New Jersey‘:  0., ‘Rhode Island‘: 0., ‘Massachusetts‘: 0., ‘Connecticut‘: 0.,
                      ‘Maryland‘: 0.,‘New York‘: 0., ‘Delaware‘: 0., ‘Florida‘: 0., ‘Ohio‘: 0., ‘Pennsylvania‘: 0.,
                      ‘Illinois‘: 0., ‘California‘: 0., ‘Hawaii‘: 0., ‘Virginia‘: 0., ‘Michigan‘:    0.,
                      ‘Indiana‘: 0., ‘North Carolina‘: 0., ‘Georgia‘: 0., ‘Tennessee‘: 0., ‘New Hampshire‘: 0.,
                      ‘South Carolina‘: 0., ‘Louisiana‘: 0., ‘Kentucky‘: 0., ‘Wisconsin‘: 0., ‘Washington‘: 0.,
                      ‘Alabama‘:  0., ‘Missouri‘: 0., ‘Texas‘: 0., ‘West Virginia‘: 0., ‘Vermont‘: 0.,
                      ‘Minnesota‘:  0., ‘Mississippi‘: 0., ‘Iowa‘: 0., ‘Arkansas‘: 0., ‘Oklahoma‘: 0.,
                      ‘Arizona‘: 0., ‘Colorado‘: 0., ‘Maine‘: 0., ‘Oregon‘: 0., ‘Kansas‘: 0., ‘Utah‘: 0.,
                      ‘Nebraska‘: 0., ‘Nevada‘: 0., ‘Idaho‘: 0., ‘New Mexico‘:  0., ‘South Dakota‘:    0.,
                      ‘North Dakota‘: 0., ‘Montana‘: 0., ‘Wyoming‘: 0., ‘Alaska‘: 0.}
    idx = 0
    for obj in rawTst_data[‘results‘]:
        user_location = obj[‘user_location‘]
        popdensity_ori[user_location] += (obj[‘polarity‘] - 1)
        popdensity[user_location] += (pred_result[idx] - 1)
        idx += 1
    # 在终端上输出不同的州的情感属性
    # 由于我们设置的 polarity 积极:0 正常:1 消极:2
    # 因此对应的不同的州对于新总统的情感值越大则越消极,越小则越积极
    print(‘popdensity_ori‘)
    print(popdensity_ori)
    print("---------------------------------------------------------")
    print(‘popdensity‘)
    print(popdensity)
    print("---------------------------------------------------------")

    # Lambert Conformal map of lower 48 states.
    fig = plt.figure(figsize=(14, 6))
    # 使用ax1, ax3 分别展示测试数据的原本情感属性值,及基于模型情感分析的结果
    ax1 = fig.add_axes([0.05, 0.20, 0.40, 0.75])
    ax3 = fig.add_axes([0.50, 0.20, 0.40, 0.75])
    # 初始化Basemap对象,获得在美国范围的地图m1
    m1 = Basemap(llcrnrlon=-119,llcrnrlat=22,urcrnrlon=-64,urcrnrlat=49,
                projection=‘lcc‘,lat_1=33,lat_2=45,lon_0=-95, ax = ax1)
    # draw state boundaries.
    # data from U.S Census Bureau
    # http://www.census.gov/geo/www/cob/st2000.html
    shp_info = m1.readshapefile(‘st99_d00‘,‘states‘,drawbounds=True)
    print(shp_info)

在可视化结果中加上各个州的缩写,这里的我们只给出了部分州的缩写,有些美国较小的东部城市没有具体列出。

# 各个州的缩写
    cities = [‘WA‘, ‘OR‘, ‘CA‘, ‘NV‘, ‘MT‘,‘ID‘,‘WY‘,‘UT‘,
          ‘CO‘, ‘AZ‘, ‘NM‘, ‘ND‘, ‘SD‘, ‘NE‘, ‘KS‘,
          ‘OK‘, ‘TX‘, ‘MN‘, ‘IA‘, ‘MO‘, ‘AR‘, ‘LA‘,
          ‘WI‘, ‘IL‘, ‘MI‘, ‘IN‘, ‘OH‘, ‘KY‘, ‘TN‘,
          ‘MS‘,    ‘AL‘, ‘PA‘, ‘WV‘, ‘GA‘, ‘ME‘, ‘VT‘,
          ‘NY‘, ‘VA‘, ‘NC‘, ‘SC‘, ‘FL‘, ‘AL‘]
    lat = [47.40, 44.57, 36.12, 38.31, 46.92, 44.24,
           42.75, 40.15, 39.06, 33.73, 34.84, 47.53,
           44.30, 41.125, 38.526, 35.565, 31.05,
           45.69, 42.01, 38.46, 34.97, 31.17, 44.27,
           40.35, 43.33, 39.85, 40.39, 37.67, 35.75,
           32.74, 61.37, 40.59, 38.49, 33.04, 44.69,
           44.045, 42.165, 37.77, 35.63, 33.86, 27.77,
           32.81]
    lon = [-121.49, -122.07, -119.68, -117.05, -110.45,
           -114.48, -107.30, -111.86, -105.31, -111.43,
           -106.25, -99.93, -99.44, -98.27, -96.726,
           -96.93, -97.56, -93.90, -93.21, -92.29,
           -92.37, -91.87, -89.62, -88.99, -84.54,
           -86.26, -82.76, -84.67, -86.70, -89.68,
           -152.40, -77.21, -80.95, -83.64, -69.38,
           -72.71, -74.95, -78.17, -79.81, -80.945,
           -81.67, -86.79]

有关美国的各个州的经纬度可在链接中查阅。

 # choose a color for each state based on population density.
    colors={}
    colors2 = {}
    statenames=[]
    # 使用cm.GMT_polar 渐变色用以展示不同情感
    cmap = cm.GMT_polar

    # 分别获得基于测试数据原本,及基于模型分析的48个大洲情感属性的最大及最小值
    # 测试数据本有标签属性值
    inverse = [(value, key) for key, value in popdensity_ori.items()]
    vmin = min(inverse)[0]
    vmax = max(inverse)[0]  # set range.
    # 测试数据情感分析结果
    inverse = [(value, key) for key, value in popdensity.items()]
    vmin_pred = min(inverse)[0]
    vmax_pred = max(inverse)[0]

    print(‘vmax:‘)
    print(vmax)
    print(m1.states_info[0].keys())
    for shapedict in m1.states_info:
        statename = shapedict[‘NAME‘]
        # skip DC and Puerto Rico.
        if statename not in [‘District of Columbia‘,‘Puerto Rico‘]:
            pop = popdensity_ori[statename]
            pop_pred = popdensity[statename]
            # calling colormap with value between 0 and 1 returns
            # rgba value.  Invert color range (hot colors are high
            # population), take sqrt root to spread out colors more.
            # 使用的cm.GMT_polar渐变色,不同州的颜色随情感越积极越红,越消极越蓝,无感状态时为无色
            # 蓝色为小于cmap的0.5,无色为cmap的0.5,红色为大于cmap的0.5
            if pop == 0:
               colors[statename] = cmap(0.5)[:3]
            elif pop < 0:
               colors[statename] = cmap(1.0 - np.sqrt((pop - vmin)/(0-vmin)))[:3]
            else:
               colors[statename] = cmap(0.5 - np.sqrt((pop - 0)/(vmax-0)))[:3]

            # 同上,colors2保存基于mllib情感分析结果的颜色
            if pop_pred == 0:
                colors2[statename] = cmap(0.5)[:3]
            elif pop_pred < 0:
                colors2[statename] = cmap(1.0 - np.sqrt((pop_pred - vmin_pred) / (0 - vmin_pred)))[:3]
            else:
                colors2[statename] = cmap(0.5 - np.sqrt((pop_pred - 0) / (vmax_pred - 0)))[:3]
        statenames.append(statename)
    # cycle through state names, color each one.
    #ax = plt.gca() # get current axes instance
    for nshape,seg in enumerate(m1.states):
        # skip DC and Puerto Rico.
        if statenames[nshape] not in [‘District of Columbia‘,‘Puerto Rico‘]:
            color = rgb2hex(colors[statenames[nshape]])
            #print(statenames[nshape])
            poly = Polygon(seg,facecolor=color,edgecolor=color)
            ax1.add_patch(poly)

    # 绘制经纬线
    m1.drawparallels(np.arange(25,65,20),labels=[1,0,0,0])
    m1.drawmeridians(np.arange(-120,-40,20),labels=[0,0,0,1])
    # 在地图上添加不同州的缩写
    x, y = m1(lon, lat)
    for city, xc, yc in zip(cities, x, y):
        ax1.text(xc - 60000, yc - 50000, city)
    ax1.set_title(‘Twitter-based sentiment analysis about Hillary ‘)

    m2 = Basemap(llcrnrlon=-119,llcrnrlat=22,urcrnrlon=-64,urcrnrlat=49,
                projection=‘lcc‘,lat_1=33,lat_2=45,lon_0=-95, ax = ax3)
    m2.readshapefile(‘st99_d00‘, ‘states‘, drawbounds=True)
    for nshape, seg in enumerate(m2.states):
        # skip DC and Puerto Rico.
        if statenames[nshape] not in [‘District of Columbia‘, ‘Puerto Rico‘]:
            color = rgb2hex(colors2[statenames[nshape]])
            # print(statenames[nshape])
            poly = Polygon(seg, facecolor=color, edgecolor=color)
            ax3.add_patch(poly)

    ax3.set_title(‘Random Forest prediction‘)
    m2.drawparallels(np.arange(25,65,20),labels=[1,0,0,0])
    m2.drawmeridians(np.arange(-120,-40,20),labels=[0,0,0,1])
    x, y = m2(lon, lat)
    for city, xc, yc in zip(cities, x, y):
        ax3.text(xc - 60000, yc - 50000, city)

    # 添加渐变色条colorbar,方便对应颜色查看情感属性
    ax2 = fig.add_axes([0.05, 0.10, 0.9, 0.05])
    norm = mpl.colors.Normalize(vmin=-1, vmax=1)
    cb1 = mpl.colorbar.ColorbarBase(ax2, cmap=cmap,
                                    norm=norm,
                                    orientation=‘horizontal‘,
                                    ticks=[-1, 0, 1])
    cb1.ax.set_xticklabels([‘negative‘, ‘natural‘, ‘positive‘])
    cb1.set_label(‘Sentiment‘)

    plt.show()

函数定义完成后,在 sparkSA.py 的最后一行调用该函数以执行它。在代码最后加上此行:

res_visulization(predictions.collect())

保存该文件后退出编辑,在 Shiyanlou_cs722 目录下, 通过spark-submit命令提交所编写好的Python脚本SparkSA.py执行程序:

程序运行结束,我们可看到每个州的原始数据及模型预测的情感属性值: 

五、总结

本次课程我们介绍了twitter api一个Twitter官方提供可用于获得推特数据的接口,并且基于此接口获得了推特上的 流式 数据,在实际应用中可利用spark streaming获得这些流式数据进行实时处理并显现当下网友的情感状态。而本次实验我们是利用spark mllib的随机森林模型进行twitter的情感分析,并且利用basemap进行可视化,通过可视化结果,我们可以直观的感受到美国今年曾经的候选总统在美国各个州的受欢迎程度。基于此课程,同学们也可以利用twitter或者微博提供的开发者接口获取网络上的数据,对不同方面(房价、物价、交通之类)的情感进行分析。

情感分析最终效果图(有时可视化效果未显现程序就已经结束,此时只需重复提交即可):

本次课程的所有源码可通过以下命令获得:

wget http://labfile.oss.aliyuncs.com/courses/722/sparkSA.py

六、课后习题

在使用spark mllib进行情感分析的例子中,很多都是使用朴素贝叶斯模型,这里我们使用的是随机森林模型,在此请同学们使用spark mllib朴素贝叶斯模型进行代码改写,并输出情感分析结果。

时间: 2024-10-15 15:56:06

使用Spark MLlib进行情感分析的相关文章

Spark MLlib之线性回归源码分析

1.理论基础 线性回归(Linear Regression)问题属于监督学习(Supervised Learning)范畴,又称分类(Classification)或归纳学习(Inductive Learning);这类分析中训练数据集中给出的数据类标是确定的:机器学习的目标是,对于给定的一个训练数据集,通过不断的分析和学习产生一个联系属性集合和类标集合的分类函数(Classification Function)或预测函数(Prediction Function),这个函数称为分类模型(Clas

情感分析的现代方法(包含word2vec Doc2Vec)

英文原文地址:https://districtdatalabs.silvrback.com/modern-methods-for-sentiment-analysis 转载文章地址:http://datartisan.com/article/detail/48.html 情感分析是一种常见的自然语言处理(NLP)方法的应用,特别是在以提取文本的情感内容为目标的分类方法中.通过这种方式,情感分析可以被视为利用一些情感得分指标来量化定性数据的方法.尽管情绪在很大程度上是主观的,但是情感量化分析已经有

基于Spark MLlib平台的协同过滤算法---电影推荐系统

基于Spark MLlib平台的协同过滤算法---电影推荐系统 又好一阵子没有写文章了,阿弥陀佛...最近项目中要做理财推荐,所以,回过头来回顾一下协同过滤算法在推荐系统中的应用. 说到推荐系统,大家可能立马会想到协同过滤算法.本文基于Spark MLlib平台实现一个向用户推荐电影的简单应用.其中,主要包括三部分内容: 协同过滤算法概述 基于模型的协同过滤应用---电影推荐 实时推荐架构分析     一.协同过滤算法概述 本人对算法的研究,目前还不是很深入,这里简单的介绍下其工作原理. 通常,

Spark MLlib Linear Regression线性回归算法

1.Spark MLlib Linear Regression线性回归算法 1.1 线性回归算法 1.1.1 基础理论 在统计学中,线性回归(Linear Regression)是利用称为线性回归方程的最小平方函数对一个或多个自变量和因变量之间关系进行建模的一种回归分析.这种函数是一个或多个称为回归系数的模型参数的线性组合. 回归分析中,只包括一个自变量和一个因变量,且二者的关系可用一条直线近似表示,这种回归分析称为一元线性回归分析.如果回归分析中包括两个或两个以上的自变量,且因变量和自变量之间

使用 Spark MLlib 做 K-means 聚类分析[转]

原文地址:https://www.ibm.com/developerworks/cn/opensource/os-cn-spark-practice4/ 引言 提起机器学习 (Machine Learning),相信很多计算机从业者都会对这个技术方向感到兴奋.然而学习并使用机器学习算法来处理数据却是一项复杂的工作,需要充足的知识储备,如概率论,数理统计,数值逼近,最优化理论等.机器学习旨在使计算机具有人类一样的学习能力和模仿能力,这也是实现人工智能的核心思想和方法.传统的机器学习算法,由于技术和

Spark MLlib KMeans聚类算法

1.1 KMeans聚类算法 1.1.1 基础理论 KMeans算法的基本思想是初始随机给定K个簇中心,按照最邻近原则把待分类样本点分到各个簇.然后按平均法重新计算各个簇的质心,从而确定新的簇心.一直迭代,直到簇心的移动距离小于某个给定的值. K-Means聚类算法主要分为三个步骤: (1)第一步是为待聚类的点寻找聚类中心: (2)第二步是计算每个点到聚类中心的距离,将每个点聚类到离该点最近的聚类中去: (3)第三步是计算每个聚类中所有点的坐标平均值,并将这个平均值作为新的聚类中心: 反复执行(

Spark MLlib算法调用展示平台及其实现过程

1. 软件版本: IDE:Intellij IDEA 14,Java:1.7,Scala:2.10.6:Tomcat:7,CDH:5.8.0: Spark:1.6.0-cdh5.8.0-hadoop2.6.0-cdh5.8.0 : Hadoop:hadoop2.6.0-cdh5.8.0:(使用的是CDH提供的虚拟机) 2. 工程下载及部署: Scala封装Spark算法工程:https://github.com/fansy1990/Spark_MLlib_Algorithm_1.6.0.git

Spark入门实战系列--8.Spark MLlib(上)--机器学习及SparkMLlib简介

[注]该系列文章以及使用到安装包/测试数据 可以在<倾情大奉送--Spark入门实战系列>获取 1.机器学习概念 1.1 机器学习的定义 在维基百科上对机器学习提出以下几种定义: l“机器学习是一门人工智能的科学,该领域的主要研究对象是人工智能,特别是如何在经验学习中改善具体算法的性能”. l“机器学习是对能通过经验自动改进的计算机算法的研究”. l“机器学习是用数据或以往的经验,以此优化计算机程序的性能标准.” 一种经常引用的英文定义是:A computer program is said

协同过滤算法 R/mapreduce/spark mllib多语言实现

用户电影评分数据集下载 http://grouplens.org/datasets/movielens/ 1) Item-Based,非个性化的,每个人看到的都一样 2) User-Based,个性化的,每个人看到的不一样 对用户的行为分析得到用户的喜好后,可以根据用户的喜好计算相似用户和物品,然后可以基于相似用户或物品进行推荐.这就是协同过滤中的两个分支了,基于用户的和基于物品的协同过滤. 在计算用户之间的相似度时,是将一个用户对所有物品的偏好作为一个向量,而在计算物品之间的相似度时,是将所有