Google Natural Language API에서 트윗의 감정 점수를 그래프로 보았습니다.
소개
자연 언어 처리를 조금 만져보고 싶었기 때문에, 간단하게 사용할 수있는 것 같은 Google Cloud Natural Language API 를 사용해 보았습니다. 이 API는 주어진 데이터의 「엔티티 분석」이나 「구문 해석」등 실시할 수 있습니다만, 이번은 확실히 재미있는 것 같은 「감정 분석」을 사용해 보았습니다.
분석할 데이터
어떤 언어 데이터의 감정을 분석할지 헤매었습니다만, 가장 친밀한 자신의 tweet를 사용해 보았습니다. 아마도 tweet이 가장 자연스러운 단어를 사용하는 방법을 가지고 있기 때문에 감정 분석하기에는 상당히 재미 있다고 생각합니다.
tweet 데이터를 얻으려면 다음 코드를 작성했습니다.
require 'twitter'
require 'uri'
class TwitterContent
def initialize()
client = Twitter::REST::Client.new do |config|
config.consumer_key = "YOUR_CONSUMER_KEY"
config.consumer_secret = "YOUR_CONSUMER_SECRET"
config.access_token = "YOUR_ACCESS_TOKEN"
config.access_token_secret = "YOUR_ACCESS_SECRET"
end
end
def get_tweets(count)
tweets = [@client.user_timeline(count: 1)][0]
remaining = count
roop_count = 200
until remaining == 0 do
@client.user_timeline(count: roop_count, max_id: tweets.last.id-1).each do |t|
remaining -= 1
if remaining == 0
break
end
unless URI.extract(t.text).empty?
next
end
tweets << t
end
if remaining < 200
roop_count = remaining
end
end
tweets.map! {|t| t.text}
end
end
덧붙여서 나의 트위터는 newspick를 공유하고 있는 것이 많았으므로, url를 포함하고 있는 것은 제외하기로 했습니다.
( #get_tweets
는 tweet를 원하는 수만큼 얻는데 쓴 메소드이지만, 우리하면서 매우 더러운 코드가 되어 있습니다...개량하고 싶다...)
Google Natural Language API
이 API의 사용법은 대부분 문서에 기재되어 있다 빠른 시작 와 같기 때문에 설명은 생략합니다. 데이터를 자바 스크립트로 처리하고 싶었기 때문에 Sinatra를 사용하여 템플릿에 전달하고 있습니다.
감정 분석 API의 반환값으로는 score
와 magnitude
가 반환되어 정의는 다음과 같습니다.
어떤 언어 데이터의 감정을 분석할지 헤매었습니다만, 가장 친밀한 자신의 tweet를 사용해 보았습니다. 아마도 tweet이 가장 자연스러운 단어를 사용하는 방법을 가지고 있기 때문에 감정 분석하기에는 상당히 재미 있다고 생각합니다.
tweet 데이터를 얻으려면 다음 코드를 작성했습니다.
require 'twitter'
require 'uri'
class TwitterContent
def initialize()
client = Twitter::REST::Client.new do |config|
config.consumer_key = "YOUR_CONSUMER_KEY"
config.consumer_secret = "YOUR_CONSUMER_SECRET"
config.access_token = "YOUR_ACCESS_TOKEN"
config.access_token_secret = "YOUR_ACCESS_SECRET"
end
end
def get_tweets(count)
tweets = [@client.user_timeline(count: 1)][0]
remaining = count
roop_count = 200
until remaining == 0 do
@client.user_timeline(count: roop_count, max_id: tweets.last.id-1).each do |t|
remaining -= 1
if remaining == 0
break
end
unless URI.extract(t.text).empty?
next
end
tweets << t
end
if remaining < 200
roop_count = remaining
end
end
tweets.map! {|t| t.text}
end
end
덧붙여서 나의 트위터는 newspick를 공유하고 있는 것이 많았으므로, url를 포함하고 있는 것은 제외하기로 했습니다.
(
#get_tweets
는 tweet를 원하는 수만큼 얻는데 쓴 메소드이지만, 우리하면서 매우 더러운 코드가 되어 있습니다...개량하고 싶다...)Google Natural Language API
이 API의 사용법은 대부분 문서에 기재되어 있다 빠른 시작 와 같기 때문에 설명은 생략합니다. 데이터를 자바 스크립트로 처리하고 싶었기 때문에 Sinatra를 사용하여 템플릿에 전달하고 있습니다.
감정 분석 API의 반환값으로는 score
와 magnitude
가 반환되어 정의는 다음과 같습니다.
본래는 분석 대상의 데이터에 맞추어, 각각의 값을 해석하면 좋은 것 같습니다. 이번은 살짝 개관하고 싶을 뿐이므로
score
만을 이용합니다.require 'sinatra'
require 'sinatra/reloader' if development?
require 'json'
require './twitter_content'
require "google/cloud/language"
get '/' do
t = TwitterContent.new()
tweets = t.get_tweets(500)
language = Google::Cloud::Language.new
sentiment_scores = []
tweets.each do |t|
sentiment_scores << language.analyze_sentiment( content: t, type: :PLAIN_TEXT).document_sentiment.score
end
scores = sentiment_scores.map! {|s| s.round(1)}
#下記
end
google api 인증에 대한 몇 가지 방법이 있다고 생각하지만 이번에는 서비스 계정으로 인증을 받고 있습니다. 자세한 내용은 여기 .
그래프용 데이터 전처리
이번에는 js의 C3.js를 사용하여 그래프 그리기를 시도했습니다. 다음 코드는 그래프를 그리기 위해 값을 전처리합니다. x軸用のカテゴリ
カテゴリごとのtweet数
全体に対してのカテゴリごとの割合
를 그래프용으로 처리하고 있을 뿐이므로, 더 스마트가 하는 방법도 있다고 생각합니다.
get '/' do
#上記
# [-1.0..1.0]を0.1刻みで作成
categorical = []
-1.0.step(1.0,0.1).each do |f|
categorical << f.round(1)
end
# カテゴリごとの数を集計
count_hash = Hash.new(0)
scores.each do |s|
count_hash[s.to_s] += 1
end
# カテゴリの値それぞれに値を貼り付ける。なかったら0
scores_hash = {}
categorical.each do |c|
scores_hash[c] = count_hash.has_key?(c.to_s) ? count_hash[c.to_s] : 0
end
# 全体に関するそれぞれの値の割合
scores_ratio = []
scores_sum = scores_hash.values.inject(:+)
scores_hash.values.each do |v|
scores_ratio << ((v.to_f / scores_sum.to_f)*100).round(1)
end
@scores = scores_hash.values
@categorical = categorical
@count = tweets.count
@scores_ratio = scores_ratio
erb :index
end
C3.js로 그래프 그리기
그리고는 view측에서 그래프를 그리는 것 뿐입니다. 이번에는 두 종류를 그려 보았습니다.
※C3.js는 D3의 래퍼이므로, D3.js를 넣을 필요가 있습니다만, D3.js v3가 필요합니다. D3.js v4에서는 움직이지 않습니다.
점수당 수
<!DOCTYPE html>
<html>
<head>
<link href="/css/c3.css" rel="stylesheet">
<script src="https://d3js.org/d3.v3.min.js"></script>
<script src="/js/c3.min.js"></script>
</head>
<body>
<p>分析対象: <%= @count %>つのtweet</p>
<div id="chart"></div>
<div id="c2"></div>
<script>
window.onload = function(){
const scores = <%= @scores %>
const categorical = <%= @categorical %>
const scores_ratio = <%= @scores_ratio%>
const chart = c3.generate({
data: {
columns: [
['scores'].concat(scores)
],
type: 'bar'
},
axis: {
x: {
type: 'category',
categories: categorical
},
y: {
label: {
text: '個',
position: 'outer-top'
}
}
}
});
}
</script>
</body>
</html>
전체에 대한 카테고리별 비율
조금 절대 수만 보아도 잘 모르기 때문에, 그 비율을 보자.
다음과 같이 변경하면 비율을 쉽게 볼 수 있습니다.
<!DOCTYPE html>
<html>
<head>
<link href="/css/c3.css" rel="stylesheet">
<script src="https://d3js.org/d3.v3.min.js"></script>
<script src="/js/c3.min.js"></script>
</head>
<body>
<p>分析対象: <%= @count %>つのtweet</p>
<div id="chart"></div>
<div id="c2"></div>
<script>
window.onload = function(){
const scores = <%= @scores %>
const categorical = <%= @categorical %>
const scores_ratio = <%= @scores_ratio%>
const chart = c3.generate({
data: {
columns: [
['scores_ratio'].concat(scores_ratio)
],
types: {
scores_ratio: 'area'
}
},
axis: {
x: {
type: 'category',
categories: categorical
},
y: {
label: {
text: '%(パーセント)',
position: 'outer-top'
}
}
}
});
}
</script>
</body>
</html>
이번에는 최신 500건의 트윗 중 url을 포함하지 않는 168개의 트윗이 분석 대상이 되었습니다.
이렇게 개관해 보면, 미묘하게 긍정적인 쪽이 많을까? 라는 느낌이군요. 물론 magnitude 등도 외시하고 있기 때문에 실제로는 뭐라고 말할 수 없습니다만, 대체로도 가시화할 수 있으면 상당히 즐거운 것입니다. 여러분도 꼭 해보세요.
해봐
어쩐지 떠올랐던 일이었습니다만, 매우 즐거웠습니다. 하지만 거기에 더해 코드의 쓸 수 없는 것을 실감했습니다. 특히 each 밖에 블록 취급 할 수없는 것이 아마추어 느낌에 빠져 나오고 있군요 ... 데이터 처리 더 잘되고 싶다.
참고
D3 Document
C3 Document
Google Natural Language API
Twitter Gem
Reference
이 문제에 관하여(Google Natural Language API에서 트윗의 감정 점수를 그래프로 보았습니다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/hirohuntexp/items/0af8b64aa18441fcb7e4
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
get '/' do
#上記
# [-1.0..1.0]を0.1刻みで作成
categorical = []
-1.0.step(1.0,0.1).each do |f|
categorical << f.round(1)
end
# カテゴリごとの数を集計
count_hash = Hash.new(0)
scores.each do |s|
count_hash[s.to_s] += 1
end
# カテゴリの値それぞれに値を貼り付ける。なかったら0
scores_hash = {}
categorical.each do |c|
scores_hash[c] = count_hash.has_key?(c.to_s) ? count_hash[c.to_s] : 0
end
# 全体に関するそれぞれの値の割合
scores_ratio = []
scores_sum = scores_hash.values.inject(:+)
scores_hash.values.each do |v|
scores_ratio << ((v.to_f / scores_sum.to_f)*100).round(1)
end
@scores = scores_hash.values
@categorical = categorical
@count = tweets.count
@scores_ratio = scores_ratio
erb :index
end
그리고는 view측에서 그래프를 그리는 것 뿐입니다. 이번에는 두 종류를 그려 보았습니다.
※C3.js는 D3의 래퍼이므로, D3.js를 넣을 필요가 있습니다만, D3.js v3가 필요합니다. D3.js v4에서는 움직이지 않습니다.
점수당 수
<!DOCTYPE html>
<html>
<head>
<link href="/css/c3.css" rel="stylesheet">
<script src="https://d3js.org/d3.v3.min.js"></script>
<script src="/js/c3.min.js"></script>
</head>
<body>
<p>分析対象: <%= @count %>つのtweet</p>
<div id="chart"></div>
<div id="c2"></div>
<script>
window.onload = function(){
const scores = <%= @scores %>
const categorical = <%= @categorical %>
const scores_ratio = <%= @scores_ratio%>
const chart = c3.generate({
data: {
columns: [
['scores'].concat(scores)
],
type: 'bar'
},
axis: {
x: {
type: 'category',
categories: categorical
},
y: {
label: {
text: '個',
position: 'outer-top'
}
}
}
});
}
</script>
</body>
</html>
전체에 대한 카테고리별 비율
조금 절대 수만 보아도 잘 모르기 때문에, 그 비율을 보자.
다음과 같이 변경하면 비율을 쉽게 볼 수 있습니다.
<!DOCTYPE html>
<html>
<head>
<link href="/css/c3.css" rel="stylesheet">
<script src="https://d3js.org/d3.v3.min.js"></script>
<script src="/js/c3.min.js"></script>
</head>
<body>
<p>分析対象: <%= @count %>つのtweet</p>
<div id="chart"></div>
<div id="c2"></div>
<script>
window.onload = function(){
const scores = <%= @scores %>
const categorical = <%= @categorical %>
const scores_ratio = <%= @scores_ratio%>
const chart = c3.generate({
data: {
columns: [
['scores_ratio'].concat(scores_ratio)
],
types: {
scores_ratio: 'area'
}
},
axis: {
x: {
type: 'category',
categories: categorical
},
y: {
label: {
text: '%(パーセント)',
position: 'outer-top'
}
}
}
});
}
</script>
</body>
</html>
이번에는 최신 500건의 트윗 중 url을 포함하지 않는 168개의 트윗이 분석 대상이 되었습니다.
이렇게 개관해 보면, 미묘하게 긍정적인 쪽이 많을까? 라는 느낌이군요. 물론 magnitude 등도 외시하고 있기 때문에 실제로는 뭐라고 말할 수 없습니다만, 대체로도 가시화할 수 있으면 상당히 즐거운 것입니다. 여러분도 꼭 해보세요.
해봐
어쩐지 떠올랐던 일이었습니다만, 매우 즐거웠습니다. 하지만 거기에 더해 코드의 쓸 수 없는 것을 실감했습니다. 특히 each 밖에 블록 취급 할 수없는 것이 아마추어 느낌에 빠져 나오고 있군요 ... 데이터 처리 더 잘되고 싶다.
참고
D3 Document
C3 Document
Google Natural Language API
Twitter Gem
Reference
이 문제에 관하여(Google Natural Language API에서 트윗의 감정 점수를 그래프로 보았습니다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/hirohuntexp/items/0af8b64aa18441fcb7e4
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
D3 Document
C3 Document
Google Natural Language API
Twitter Gem
Reference
이 문제에 관하여(Google Natural Language API에서 트윗의 감정 점수를 그래프로 보았습니다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/hirohuntexp/items/0af8b64aa18441fcb7e4텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)