物欲購入目録日誌 写真館
スポンサーサイト
--.--.-- (--:--) スポンサー広告
Twitterでつぶやく
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
Twitter クライアント シェア調査 2012年7月
2012.07.11 (01:34) プログラミングtrackback(0)comment(0)
Twitterでつぶやく
twitter-japan-jobs.jpg

電車でスマートフォンを使ってtwitterをやっている人が多いんだけど、、中にはそれどんなクライアントソフトだよ?と思うような見たことも聞いたことみないtwitterクライアントソフトを使っている人もいたりしているので、、

実際に世間の人はどのようなtwitterクライアントソフトを使っているのか調査してみた。

調査方法はTwitter Stream APIからtweet情報を取得し、クライアントソフトを抽出して集計。
集計対象は言語設定を日本語にしているユーザが対象です。

集計期間は昨日の昼から本日の深夜まで約14時間収集しました。

収集したtweetは約26万tweetで、抽出したクライアント数は5800もありました。

結果は以下に示していますが、クライアントのシェアとしては"Twitter for iPhone"がわずかに"Twitter for Android"を上回りました。

これ以上は推測ですが、twitterクライアントの割合がiPhone[16%]とAndroid[13%]のシェアが比例するとすると、全部のAndroid端末をあわせてもまだiPhoneのほうが多いというなかなか面白い結果となっております。

3位はwebからの利用ですね。

この結果から日本ではモバイル端末からの書き込みが圧倒的に多いことも推測できてこれも面白い。

ちなみにオイラがつかっているTweetDeckのシェアが1[%]程度しかないのにはちょっとがっかり。

みんなもっとつかているとおもってたわ。(・∀・)

●調査期間 2012-07-10T11:30~2012-07-11T01:30 (14時間)
●総日本語tweet数: 264,981
●抽出クライアント数: 5,802

結果)

**** Twitter クライアント 頻度 割合[%] ***
Twitter for iPhone 42372 15.990580456712
Twitter for Android 34974 13.198682169665
web 26860 10.1365758299652
Keitai Web 20161 7.60847004124824
twittbot.net 15030 5.67210479241908
twicca 14254 5.37925360686238
ついっぷる/twipple 9300 3.50968560009963
Janetter 7585 2.86246938459739
SOICHA 7070 2.66811582717251
Echofon 5901 2.22695212109547
Tween 4505 1.70012189553213
ついっぷる for iPhone 4247 1.6027564240455
jigtwi 3229 1.21857793577653
TweetDeck 3057 1.1536676214521
Twipple for Android 2987 1.12725063306426
Tweet Button 2662 1.00460032983497
Tweetbot for iOS 2485 0.937803087768557
Mobile Web 2443 0.921952894735849
モバツイ / www.movatwi.jp 2389 0.901574075122367
モバツイ / www.movatwi.jp . 1823 0.687973854729207
TweetList! 1739 0.656273468663791
Saezuri 1702 0.642310203373072
ついっぷる for iPhone 1673 0.631366022469536
yubitter 1656 0.624950468146773
YoruFukurou 1446 0.545699502983233
ツイタマ 1379 0.520414671240579
EasyBotter 1373 0.518150357950193
jigtwi for Android 1283 0.48418565859439
ShootingStar 1239 0.467580694464886
Twipple for Android 1115 0.420784886463558
dlvr.it 1019 0.384555873817368
Tweet ATOK 893 0.337005294719244
OpenTween 893 0.337005294719244
TweetCaster for Android 796 0.300398896524657
HootSuite 763 0.287945173427529
ツイ助。 734 0.277000992523992
ついっぷる Pro for iPhone 720 0.271717594846423
twitterfeed 715 0.269830667104434
Twitter for iPad 629 0.237375509942222
Twil2 (Tweet Anytime, Anywhere by Mail) 614 0.231714726716255
twitcle 590 0.222657473554708
Tweetlogix 560 0.211335907102773
BotMaker 543 0.204920352780011
mixi ボイス 542 0.204542967231613
Krile2 536 0.202278653941226
TwitBird 510 0.192466629682883
ニコニコ動画 497 0.187560617553711
Seesmic 446 0.168313954585423
Instagram 422 0.159256701423876
Teewee 417 0.157369773681887
TweetList Pro 400 0.150954219359124
Twipple Pro for Android 370 0.13963265290719
モバツイtouch 359 0.135481411874814
TwitCasting 327 0.123405074326084
Twitter for Mac 318 0.120008604390503
Twitter for iAppli 288 0.108687037938569
twitbeam[ツイットビーム] 275 0.103781025809398
foursquare 271 0.102271483615806
Ustream.TV 267 0.100761941422215
PlayStation®Vita 264 0.0996297847770218
モバツイsmart / www.movatwi.jp 264 0.0996297847770218
Twit for Windows 263 0.0992523992286239
Google 253 0.0954785437446458
Facebook 244 0.0920820738090656
ツイート数カウントくん 238 0.0898177605186787
ついっぷる for iPad 231 0.087176061679894
ShootingStarPro 223 0.0841569772927116
Plume for Android 220 0.0830248206475181
hamoooooon 214 0.0807605073571313
モバツイ 207 0.0781188085183466
Janetter for Mac 204 0.0769866518731532
Twibow 196 0.0739675674859707
Twittelator 170 0.0641555432276276
Movatter 169 0.0637781576792298
twiroboJP 163 0.061513844388843
Silver Bird 151 0.0569852178080693
\( 'ω')/ウオオオオオアアアーーーッ! 136 0.0513244345821021
Photos on iOS 133 0.0501922779369087
Ameba_Blog 124 0.0467958080013284
Twitter for BlackBerry® 123 0.0464184224529306
リプライ数チェッカ 121 0.045663651356135
makebot ツイッター便利機能/ボット作成サービス 119 0.0449088802593393
Osfoora for iPhone 117 0.0441541091625437
コカ・コーラ パーク 116 0.0437767236141459
P3:PeraPeraPrv 115 0.0433993380657481
Get! PocketVegas 109 0.0411350247753613
FC2 Blog Notify 103 0.0388707114849744
Tabtter 101 0.0381159403881788
Ameba smartphone 101 0.0381159403881788
Tumblr 98 0.0369837837429853
livedoor Blog 97 0.0366063981945875
rakubo2 94 0.0354742415493941
Hatena 94 0.0354742415493941
Twitpic 91 0.0343420849042007
ツイ廃あらーと 90 0.0339646993558029
PSPtter 89 0.0335873138074051
KuroTwi 85 0.0320777716138138
チャーハン諸島 83 0.0313230005170182
スマホでCHANCE 80 0.0301908438718248
albo 77 0.0290586872266313
fuyutiger 75 0.0283039161298357
メガネケエス 74 0.0279265305814379
Crowy 73 0.0275491450330401
yabmin 73 0.0275491450330401
Hotpepper 71 0.0267943739362445
myAffili.net 71 0.0267943739362445
ロケタッチ(loctouch) 70 0.0264169883878467
twicli 68 0.0256622172910511
ニコニコニュース 68 0.0256622172910511
Tweet Battery 67 0.0252848317426532
iOS 67 0.0252848317426532
ラーメン大陸 66 0.0249074461942554
ついっぷる Pro for iPad 64 0.0241526750974598
ぺろったー Perottr 63 0.023775289549062
運命のクランバトル 61 0.0230205184522664
1000万円懸賞 61 0.0230205184522664
TweetConsole 60 0.0226431329038686
ついっぷる Pro for iPhone 59 0.0222657473554708
TWEET command 59 0.0222657473554708
ニコニコ生放送 58 0.021888361807073
TwitPal 58 0.021888361807073
ついっぷる for iPad 58 0.021888361807073
今日も一日おさるったー三昧 57 0.0215109762586752
Camera on iOS 57 0.0215109762586752
DIVA.NET 55 0.0207562051618795
Colotwi 54 0.0203788196134817
SeesaaBlog 53 0.0200014340650839
Paper.li 53 0.0200014340650839
儲かる!受信箱 53 0.0200014340650839
Feel on! (iPhone) 52 0.0196240485166861
My365 49 0.0184918918714927
SimplyTweet 49 0.0184918918714927
TwitRocker2 for iPhone 48 0.0181145063230949
読書メーター 48 0.0181145063230949
Tabtter Free 48 0.0181145063230949
みについ 48 0.0181145063230949
Realtime love 47 0.0177371207746971
|ヮ╹๑) 47 0.0177371207746971
twithitter.com 46 0.0173597352262992
TweetMe for iPhone 45 0.0169823496779014
gohantabeyo.com 44 0.0166049641295036
Häagen-Dazs PRESENT COLLECTION 44 0.0166049641295036
yoono 43 0.0162275785811058
MetroTwit 42 0.015850193032708
jugem_blog( jugem.jp ) 41 0.0154728074843102
LB8 Streaming 41 0.0154728074843102
WordTwit Plugin 40 0.0150954219359124
にせほ脳 39 0.0147180363875146
REFLEC BEAT limelight 38 0.0143406508391168
TweetMe for S!アプリ 37 0.013963265290719
IFTTT 37 0.013963265290719
育成ゲーム MEGU 37 0.013963265290719
find_keyword_api_dev 37 0.013963265290719
Twipple Pro for Android 37 0.013963265290719
Twitter for Windows Phone 36 0.0135858797423211
pochitter 34 0.0128311086455255
ポイントCM 34 0.0128311086455255
YouTube on iOS 34 0.0128311086455255
棒読みちゃん 33 0.0124537230971277
mikutter 33 0.0124537230971277
Feel on! (Android) 33 0.0124537230971277
ra 33 0.0124537230971277
find_keyword_api_dev5 32 0.0120763375487299
アスク!リツイート 32 0.0120763375487299
RakutenSuperRecommend 31 0.0116989520003321
Togetter 31 0.0116989520003321
find_keyword_api_dev3 31 0.0116989520003321
twippa 30 0.0113215664519343
p_ran_ 30 0.0113215664519343
・・・
スポンサーサイト
OpenMPでベンチーマーク取って遊んでみた!
2012.06.09 (23:27) プログラミングtrackback(0)comment(0)
Twitterでつぶやく

openmp_color.jpg

ちょっと、OpenMPで遊んでみた。ちゃんとスレッドで並列化されるのかベンチマークとってみたわ。
作ったソースは以下の様な感じの、ラプラス方程式をガウス・サイデイル法で解くのにかかる時間を測定するよ。

コンパイルはg++-fopenmpでコンパイルした。


//
// 【laplace.cc】
//
// OpenMPを用いてラプラス方程式をガウス・サイデイル法で
// 解くのにかかる時間を測定する
// 利用スレッド数は環境変数"OMP_NUM_THREADS"で指定しておく
//
// (コンパイル方法)
//
// $ g++ -fopenmp laplace.cc
//
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <math.h>
#include <sys/time.h>
#include <omp.h>
using namespace std;

// 大域変数
const int Xgrid = 700;
const int Ygrid = 700;
const double dx = 0.002;
const double dy = 0.002;
const double tol= 1.0E-6;

// 時間測定用 関数
double gettimeofday_sec(){
struct timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_sec + tv.tv_usec * 1e-6;
}

// グリッドの初期化関数
void initialize(double** u,int** flag){
// Circle 1
double ox1 = 0.3,oy1 = 0.3;
double radius1 = 0.2;
double value1 = 30.0;

// Circle 2
double ox2 = 0.7,oy2 = 0.6;
double radius2 = 0.06;
double value2 = -20.0;

// ローカル変数
double x = 0.0,y = 0.0;

for(int i = 0;i < Xgrid; i++){
for(int j = 0;j < Ygrid; j++){
x=static_cast(i) * dx;
y=static_cast(j) * dy;
// Circle 1
if(pow((x-ox1),2.0)+pow((y-oy1),2)-pow(radius1,2.0)<=0.0)
{
u[i][j] = value1;
flag[i][j] = 1;
}
// Circle 2
else if(pow((x-ox2),2.0)+pow((y-oy2),2.0)-pow(radius2,2.0)<=0.0)
{
u[i][j] = value2;
flag[i][j] = 1;
}else{
u[i][j] = 0.0;
flag[i][j] = 0;
}
}
}
}

// main
int main(void){
int i,j;
double start= 0.0,end = 0.0;
double err = 0.0,diff = 0.0;
// データ用配列
double** u;
double** uu;
int** flag;
int thread_num = 0;

// グリッドを初期化
u = new double*[Xgrid];
uu = new double*[Xgrid];
flag = new int*[Xgrid];
for(int i = 0;i < Xgrid; i++){
u[i] = new double[Ygrid];
uu[i] = new double[Ygrid];
flag[i] = new int[Ygrid];
}
initialize(u,flag);

// 時間計測開始
start = gettimeofday_sec();

do{
#pragma omp parallel private(i,j,diff)
{
// スレッド数取得
thread_num = omp_get_num_threads();
#pragma omp for
// copy
for (i = 1; i < Ygrid - 1; i++){
for (j = 1; j < Xgrid - 1; j++){
uu[i][j] = u[i][j];
}
}
#pragma omp for
// update
for (i = 1; i < Ygrid - 1; i++){
for (j = 1; j < Xgrid -1; j++){
if(flag[i][j] != 1){
u[i][j] = 0.25 *
(uu[i][j-1] + uu[i][j+1] + uu[i-1][j] + uu[i+1][j]);
}
}
}
#pragma omp single
{ err = 0.0; }
#pragma omp for reduction(+:err)
for (i = 1; i < Ygrid -1; i++){
for (j = 1; j < Xgrid-1; j++){
diff = uu[i][j] - u[i][j];
err += diff * diff;
}
}
}
}
while (err > tol);
// 時間計測終了
end = gettimeofday_sec();
cout << thread_num << "スレッド: " << (double)(end - start) << endl;
return 0;
}


結果はこんな感じ。

opnmp2.png

使ったマシンは自分のCorei7(4コア,8スレッド)のiMacで測定しました。
クワッドコアなので4CPUまでは速度がほぼ線形に向上したんだけど、、

それ以上の並列度はハイパースレッディングでみかけの8CPUなので、L2キャッシュなどを多用する数値計算などではあまり速度向上が見込めない結果になった。

なんかHTってマジで計算速度倍になるかのように素人考えで思っていたけど、そうでもなかったわ。
Rubyでgoogle Suggest APIを利用する
2012.05.16 (00:57) プログラミングtrackback(0)comment(0)
Twitterでつぶやく
explore-google-suggest.png



以前にGoogleのSuggest APIを用いてGoogleの推薦語を取得するスクリプトを紹介したけど、、最近やったら動かなくなっていたので、もう一度清書してみた。

実際に問題になっていた部分はgoogle APIがUTF-16の文字列を返してくることがあって、その場合にXMLのパーサーとして利用しているrexmlがエラーを返すためにうまく処理できないことがあったので修正してみた。


# 【suggest.rb】
#
# usage: $suggest.rb
#
$KCODE="u"
require 'net/http'
require 'cgi'
require 'kconv'
require 'rexml/document'

class Suggest
  # init
  def initialize()
  begin
    @http = Net::HTTP.new('www.google.co.jp', 80)
  rescue
  puts "初期化に失敗しました"
    return nil
    end
  end

  # request
  def request(query)
    query = "/complete/search?output=toolbar&q=#{CGI::escape(query)}&hl=ja"
    begin
      req = Net::HTTP::Get.new(query)
      res = @http.request(req)
      # XMLを返却
      return res.body.toutf8
    rescue
       puts "リクエストに失敗しました: #{query}"
      return nil
    end
  end

  # get
  def get(query)
    doc = REXML::Document.new(request(query))
    words = []
    doc.get_elements('//toplevel/CompleteSuggestion').each do |e|
      words << e.elements['suggestion'].attributes['data'].toutf8
    end
    # 取得した配列を返却
    return words
  end
end

# main 関数
if __FILE__ == $0
  s = Suggest.new()
  s.get(ARGV[0]).map{|s| puts s}
end


実行結果はこんなん。

$ ./suggest.sh 'アキバ'
アキバレンジャー
アキバズトリップ
アキバ総研
アキバチューナー
アキバガレージ
アキバズトリップ 攻略
あきばおー
秋葉工房
秋葉神社
秋葉

たまにsuggest結果をブラウザ経由じゃなくてテキストで簡単にほしいときなどに便利ですな。
Woopraでgoogleからの検索クエリが取得できなくなったでござる。
2012.04.27 (00:08) プログラミングtrackback(0)comment(0)
Twitterでつぶやく
woopra.jpg


リアルタイムアクセス解析ソフトのWoopraや他のアクセス解析サービスもそうみたいだけど、、googleのアカウントでログインした状態で検索ページで検索するとhttps://www.google.comにリダイレクトされて検索クエリが第三者に傍受されないように暗号化されるらしい。

第三者はwoopraなどのサービスでgoogleは第三者じゃないので、分かるのでwoopraなどのサービスで軒並み検索ワードが調査できない有様。(・∀・)

googleアナリティクスは取得できるらしい、、なんちゅ~セコイんだよ。

http://www.itmedia.co.jp/news/articles/1110/19/news077.html
Rubyのクローラー(スパイダー)フレームワーク Anemone と Mechanize #eurekaao
2012.02.22 (01:49) プログラミングtrackback(0)comment(0)
Twitterでつぶやく
anemone.jpg


webの情報を収集収集しようとすると必然的に必要になってくるのがクローラープログラム。

Rubyには優秀なスクレイピングツールのMechanizeというフレームワークが提供されていて、オイラはこれでクローラーを作っていたのですが、、最近、Anemone(アネモネ)というクローラーに特化したフレームワークがあるというのでちょっと触ってみた完走と、Mechanizeの違いについて。

Anemone An easy-to-use Ruby web spider framework
http://anemone.rubyforge.org/

Mechanizeがどちらかというと汎用なスクレイピングツールという側面が強い。そしてMechanizeは組み方によってはクローラーも作ることができる。

anemoneは完全にクローラー用のフレームワークとして設計されている点が大いに違うという印象。
用意されているmethodやデータ保存用にDBが簡単に組み込めるなど、、非常に面白い。


これから、クローラーを作る人がいたら、anemoneベースに作成してもいいのではないかと思う。

インストール方法はgemで入れられるので一発


$ gem install anemone

サンプルコードはこんな感じ

--
#! /usr/bin/ruby
#
# [exp anemone]
#
$KCODE="u"
require 'rubygems'
require 'anemone'
require 'hpricot'
require 'kconv'

Anemone.crawl("http://blog.livedoor.jp/geek/") do | anemone |
  anemone.on_every_page do |page|
    # BODYをHpricotに渡してパーズする
    doc = Hpricot(page.body)
    # タイトルを表示
    puts (doc/"title")[0].inner_html.toutf8
  end
end
--
ここで一つ注意なのが、、オイラが以前扱っていたようにanemoneは標準のHTMLパーサーとしてnokogiriを使う。
このnokogiri(ibxml2)がくせもので、Mechanizeとnokogiriで発生した一部の日本語のページで文字化けするという事象がここでも生じる。

http://tachiphoto.blog61.fc2.com/blog-entry-1479.html


それを回避するためには、nokogoriを使わずに、馬鹿正直にnokogiriを使わずにhpricotを利用してHTMLを渡せばよい。ただそれだけ。これで文字化けの問題は回避される!!(`・ω・´)キリ ...
Rubyで Google PageRank(ページランク)を取得する方法
2012.01.24 (21:03) プログラミングtrackback(0)comment(0)
Twitterでつぶやく
1278493147013949200.png


ネットを調べれば、やりたいことのサンプルコードは転がっていて比較的簡単に入手できるが、

実際には情報が古かったり、情報が分散されていてタスクが難しくなることががあるので簡単なことでも情報をまとめておくことが大事である。

ということを踏まえてGoogleのPageRankをRubyのスクリプトから直接参照できるやり方をご紹介。

まず、以下のページのサンプルコードを拝借してくる。

DZone Snippets
http://snippets.dzone.com/posts/show/3284

googleのPageRankはgoogleツールバーのAPIを用いて取得するのですが、その際にチェックサム値を算出する必要があるこのタスクをこのスクリプトは全部やってくれる。

しかし、このスクリプトを実行するだけでは取得することはできない。なぜならちょっと前にgoogle のツールバーのAPIのURLが変更になっているからです。よって以下のようにURLを修正する。


# このURLが古くなっている
# "http://toolbarqueries.google.com/search?client=navclient-auto&hl=en&ch=#{cn}&ie=UTF-8&oe=UTF-8&features=Rank&q=info:#{URI.escape(@uri, /[^-.!~*'()a-zA-Z\d]/)}"
# このURLが新しいURL
"http://toolbarqueries.google.com/tbr?client=navclient-auto&hl=en&ch=#{cn}&ie=UTF-8&oe=UTF-8&features=Rank&q=info:#{URI.escape(@uri, /[^-.!~*'()a-zA-Z\d]/)}"


このURLが古くなっているという記事は

http://www.suzukikenichi.com/blog/google-pagerank-unavailable-on-3rd-party-tools/

などで参照されている。
このように情報が分散してしまうと途端に情報を統合して理解するこが難しくなってしまう。

ということで、実際に上記のコードで買い換えて実行してみると


$ ./google-pr.rb 'http://tachiphoto.blog61.fc2.com/'
2

と返却されオイラのブログのページランク値が'2'であることがわかる。
当然ながら、リストなどを渡せは複数のページランク値を一度に取得することも可能となります。
Think Pad X60sの液晶に亀裂が orz
2012.01.09 (23:13) プログラミングtrackback(0)comment(0)
Twitterでつぶやく
IMG_0411.jpg


すごい高い場所から落としたわけでも、、なにかすごい圧がかかったわけでもないですが、外で開発環境にログインする端末として使っているThinkPadX60sの液晶がなんか割れたというかおかしくなった?

画面中央に線が入っている。たぶん、完全に割れているだけではないけど、亀裂が入っているんだと思う。orz

あんまりひどくないので、気にならないといえば気にならないですが、、気になると言えば気になる。

う~ん、中古で安く買ったので修理とかするよりも、、もう一台買ったほうが安いといえば安いんだけど、せっかくなのでいけるところまで行きたい。

というのでいいこと考えた!!↓


IMG_0414.jpg

(・_☆) キュピーン!! 完全に治っておる!!!というか、、

ま~そんなわけないですが、、、とりあえず、、応急処置だな。

[Ruby] Sanitize : HTMLから不用なタグを消去する(サニタイズ)ライブラリ
2011.12.26 (23:43) プログラミングtrackback(0)comment(0)
Twitterでつぶやく
Basics-of-HTML.jpg


HTMLから不用なhtmlのタグを消去することをサニタイズというらしい、、

プログラムを作っていると、、HTMLからタグを取るのが結構めんどくさい場合ってありますよね。そいう場合はruby gemの Sanitizeというライブラリを使うと便利です。

http://wonko.com/post/sanitize

・install

$ gem install sanitize



・example


#! /usr/bin/ruby
$KCODE="u"
require 'rubygems'
require 'sanitize'

html = '<a href="http://foo.com/">foo</a>'
puts Sanitize.clean(html)




$./ex.rb
foo



タグの削除の方法とか、特定のものを残してそれ意外を削除するなど、いろんなパタンで削除できるらしいですな。ちまちま正規表現でなんとかしようとするよりもはるかに便利!

詳しくは上記のページをご参照。
[ Ruby ] twitter スパム推定で特徴選択
2011.10.14 (00:26) プログラミングtrackback(0)comment(0)
Twitterでつぶやく
shiwasu.jpg


オイラが作っているtwitter bot(@tachi_pic_bot)にスパム推定(スパム検出)機能を実装しているのですが、もう少し面白いことはできないかといろいろ改造していじくってみた。

とりあえず、いらない素性を利用しなくしてもっと精度が上がらないかと思ったので、feature selection(特徴選択)を実際に簡単なものでやってみた。

特徴選択はK個の全て特徴量を機械学習で利用するのではなくそのうちで有用な素性のみを選び出す方法。

特徴選択を実施する理由は大きく分けて2つ

(1) 目的変数と無関係な特徴量を使わないことで予測精度を向上させる.
(2) 学習された関数を,定性的に解釈しやすくする.

がある。オイラの目的としては主に(1)番目を目論んでおる。

実現方法も2つあって

(1) 事前に素性をある指標によってフィルタリングするフィルター法
(2) 特徴量の部分空間をえらんで実際に学習し交差検定を行い精度を確認して最も精度の出る素性セットを探すラッパー法

ここでオイラは(1)のフィルター法を実際にやってみた。

計算する指標は簡単な相関係数を計算してみた、んで計算した結果が以下の図。


corr.png


結構バラバラ。ほんとにいいのかどうかわからんかったので、実際に一番数値の高い4つの素性と数値のわるい4つの素性のみを使って実際に学習検証をやってみた。精度が以下のもの

ベスト4
- 全tweet数
- フォロー数
- フォロワー数
- 直近20 tweetの総文字数
82.6 [%]

ワースト4

- お気に入り数
- 直近20tweetにおいてハッシュタグが含まれている割合
- など

63.2 [%]


となってかなり綺麗な結果になって自分でもびっくりした。なるほどって感じ。
とりあえず、必要なさそうな素性を削除して再度ベストセットに近い素性セットで精度を図ると

97.2 [%}


程度まで上昇して、素性選択が結構有効であることがわかった。

今度は情報ゲインとかもうちょっとこったことを計算してみる。toro_mune.gif
[ Ruby ] twitter bot ( @tachi_pic_bot )の改造と宣伝
2011.10.06 (00:17) プログラミングtrackback(0)comment(0)
Twitterでつぶやく
FI2622896_2E.jpg


最近オイラが作っているツイッターボットの機能追加などをいろいろしたので書いてみる。

オイラのツイッターボットは @tachi_pic_bot というもので、オタクな話題をつぶやいたりします。

主な機能は

●RSS情報投稿機能
大量のRSS情報を取得して,その中からオタクっぽい話題を機械学習で推定/分類してオタクっぽい話題に関して呟きます。推定器にはSVMを利用。

●google急上昇ワード投稿機能
googleの急上昇ワードを取得して、上位5位を呟きます。
またその中から気になる語に関してリンク付きでご紹介します。気になるワードの選定方法はgoogleの急上昇ワードのスニペット情報を形態素解析して、モデルデータを用いて推定/分類し一番、分類精度の高い語を1個選びます。分類器にはナイーブベイズ分類器を利用します。

●スクレイピング投稿機能
RSSでは取得できない、もしくはRSS情報を配信していない情報元に対して、特定URLのhtmlをクロール、その後データの抽出(スクレイピング)を実行し、情報を再構成して呟きます。

今はアニメ・ゲーム系のイベントが盛んな以下の2つのページのスケジュール・ページを1ホップクロールして今月、来月のスケジュールまで取得します。

ロフトプラスワン


阿佐ヶ谷ロフト

※この部分が最近、改造・調整した部分になります。これまでスクレイピングの精度が今ひとつ(やっつけ)だったので日時・曜日・URLをもっと綺麗に取得できるようにしたのとRubyのMechanize2.0.1対応を実施しました。

例はこんな感じ

--
[LOFT/PLUS ONE] 2011年10月24(月) 第65回アニメスタイルイベント bit.ly/qkychf bit.ly/oePkDo
--

正直かなり、よくなった感じです。が一点だけ改造の余地があって、アニメ系のイベント情報のみを出力するようになっているのですが、、そのアニメ系かそうでないか?というのを私で用意したキーワードの正規表現マッチングのみでやっているのが、まだ改造の余地があります。

このキーワードマッチでは、こっちが想定していないワードの場合は簡単に取りこぼしてしまうんですな。

一番、怖いのがアニメなどの新番組のタイトル名だけで構成されたイベントなど、、一言”アニメ”とか書いてくれればひっかけられるのですが、、全てのアニメ番組の情報キーワード用意はしていられない。

これを回避するためには、このタイトルに含まれている情報がアニメ系かそうでないかという推定を実施しないといけなくなり、難易度やコーディング量が増えます。

やるとすると以下のような仕様かと思います。

1) スケジュールのデータと用意したキーワードのマッチングを実施する、マッチしたらアニメ系とする。

2) マッチしないデータは、イベントタイトル名でgoogle検索を実施、結果が取得できたら検索結果上位K件のスニペット情報を取得。スニペットを形態素解析を実施し、キーワードベクトルを生成し(3)へ進む。

google検索で1件もヒットしない場合は(2-1)へ進む。
※イベントタイトルは長いものはヒットしないもしくは極端に結果が少ない場合があります。その場合は検索結果の信頼性が低いと判断し、その結果からキーワードベクトルを生成しないほうがよいと思わます。

2-1) イベントタイトルを形態素解析し、固有表現を抽出、抽出された固有表現でgoogle検索を実施し、キーワードベクトルを生成し(3)へ進む。

☆この固有表現抽出というのがかなり難しい!

3) 取得できたキーワードベクトルを用いて分類器で推定する。推定はナイーブベイズのほうがいいね。
ナイーブベイズで分類結果がアニメ系であれば、そのデータを呟く。

といった感じでがんばらんといけない。
難しいのは(2-1)だけなので、ちょっとコードが長くなるけど、改造できななくもいけど、、明らかにオーバースペック!!

●スパムアカウント推定機能

スパムアカウント推定機能はこの中では一番ボリュームのある機能で推定の検証機能などを含めて約3000行のコードになります。基本的には以下のような図でわかるように


twitter_spam.png


twiter botをやっていると不特定多数のスパムっぽいユーザーの人から比較的多くフォローされます。

最初に作ったBotの仕様ではフォローしてくれたユーザーさんには無条件かつ自動でBotのほうもフォローするようにしていたのですが、これが問題でそうするとスパムのアカウントも普通の人のアカウントもフォローしてしまうことになって、Botのタイムラインがすごいひどいことになるので、、Botであろうとスパムじゃない人だけをフォローしたいという趣旨に基づいて、フォローしてくれた人をスパム推定させてもらって、スパム推定判定で比スパムとなったユーザーさんだけを自動的にフォローするようにしました。

結果はこのページを見てもらいたいのですが、このページのアカウントの人だけが比スパムと判定されたアカウントとなっております。

http://twitter.com/#!/tachi_pic_bot/following


結果わかるように、、比スパムと判定するpresicionはかなり高精度で精度は90%以上は達成しているのではないかと思いますが、、逆にrecallのほうはじゃっかん、普通の人もスパム判定でスパムとしてしまっているケースもあるようで、ちょっと取りこぼしがあることはありますが、実用上まったく問題ない程度の判定精度ではないと思います。分類問題としてはタスクの難易度はそんなに高くない?

●ハッシュタグ ランキング機能

最後に、昨日思いついたので即興で作ったハッシュタグランキング機能。
この機能はtwitter APIでも、ストリームデータのAPIを利用して統計値を集計します。

twitterのストリームデータはtwitter全部の流量の約1%に相当?するデータを取得できるAPIでこの1%が全体からの無作為サンプリングの結果だと仮定すると、ストリームデータのハッシュタグの個数の頻度のランキングを生成すると今twitterでつぶやかれているリアルな話題の一部を簡単に提供することができるのではないかと思って付くてみました。

予想としては夜のアニメタイムが始まると番組のハッシュタグがバーストしてくる様子が見れたら面白いと思って夜のアニメタイムの PM 10:00 ~ AM 3:30 まで30分間隔で日本語のツィート文からハッシュタグを抜き出して頻度を数えるようにしました。

本日から集計しております。取得したデータはtweetの他にファイルにダンプしてるので、2次加工して解析も実施出来る予定です。



--
[HashTag Ranking 占有率] 1位 #タイトル 0.54[%] 2位 #学校 0.26[%] 3位 #nicovideo 0.13[%] [集計時間: 2011.10.05 22:30 ~ 2011.10.05 23:00]
--

なんでタイトルとかきているのかちょっと疑問ですが、、とりあえず今試運転中。
Ruby gemの tweetstream (1.1.1) の認証方法
2011.10.05 (02:06) プログラミングtrackback(0)comment(0)
Twitterでつぶやく
Ruby gemの tweetstream (1.1.1) の認証方法なんですが、、どうもサンプルコードが全て古い例なのでやくに立たないのでこのように書くと書いておく


require 'rubygems'
require 'tweetstream'

#==
# 認証用情報
#==
CONSUMER_KEY = 'XXXX'
CONSUMER_SECRET = 'XXXX'
OAUTH_TOKEN = 'XXXX'
OAUTH_TOKEN_SECRET = 'XXXX'

def main()
begin
# 認証
TweetStream.configure do |config|
config.consumer_key = CONSUMER_KEY
config.consumer_secret = CONSUMER_SECRET
config.oauth_token = OAUTH_TOKEN
config.oauth_token_secret = OAUTH_TOKEN_SECRET
end
# Twitter Stream API情報取得
TweetStream::Client.new().sample do |status|
puts status.text
end
end
end

# main 関数
if __FILE__ == $0
#メインプログラム
main()
end

認証方法がOAuthに変わった影響で認証方法が変更になっております。詳しくは

https://github.com/intridea/tweetstream
Ruby の timeoutで割り込み処理を実行する
2011.10.05 (01:45) プログラミングtrackback(0)comment(0)
Twitterでつぶやく
ikuno_kuruma.jpg


Rubyで以下のような処理をしたいなぁ~と思ったのですが、イベントドリブンなプログラムを書いたことがないのでどうやっていいのか疑問状態に、、

(1) ある時間ず~っとなのかの処理をしていて、一定時間経過もしくは一定時間毎になんかの別の処理を実行する。
(2) ある一定時間でプログラムが終了する。


このような処理を割り込み処理っていうんでしょうか?あまりよくわからんかったし、しかもプログラム例もあまりかかれていないのでどうやってrubyで書けていいのか調べているとtimeoutというものがあるらしい。

http://www.ruby-lang.org/ja/old-man/html/trap_timeout.html

これは使えるなと思って実際に上記の(1),(2)の処理を書いてみた。
たぶん、こんな感じのコードになるはず。


#! /usr/local/bin/ruby
#
# timeoutを使って以下の2つのタスクを実行
#
# (1) 一定時間経過したら,ある処理を実行する
# (2) 一定時間経過したら,プログラムを終了する
#
$KCODE="u"
require 'timeout'

# 時間設定
PROGRAM_TIMEOUT = 30
TASK_TIMEOUT = 10
# 乱数格納用配列
rd = []

begin
#
# (2) プログラムの継続時間を設定
# 一定時間(PROGRAM_TIMEOUT[sec])
# 経過したらプログラムを終了
#
timeout(PROGRAM_TIMEOUT){
begin
# (1) タスクの割り込み
# 一定時間(TASK_TIMEOUT)
# 経過したらなんかの仕事を実行
#
timeout(TASK_TIMEOUT){
# 無限ループで乱数を作って配列に入れていく
while true do
sleep 1
rd.push(rand)
end
}
# timeoutは"Timeout::Error"でキャッチしないといけない
rescue Timeout::Error
# タスクの割り込み
sum = 0.0
rd.map{|num| sum += num}
puts "平均: #{sum/rd.size.to_f}"
# メモリをフリー
rd = []
# 繰り返します
retry
end
}
# プログラムの終了はここ
rescue Timeout::Error
puts "プログラムを終了します"
end


2つのブロックが入れ子担っていて1つめが一定時間でプログラムを終了させるブロック、2番目がある一定時間毎になんらかの処理をするブロックになっています。

例では配列に乱数を1秒に1個づついれて平均を計算して出力している計算を10秒ごと実行し,30秒経過するとプログラムが終了します。

こんな感じでいいのかしらね?
RubyのMechanizeとnokogiriで文字化けするならhpricotを使えばよいさ!!
2011.10.04 (01:16) プログラミングtrackback(0)comment(0)
Twitterでつぶやく
nori_pc.png


Rubyでクローラーのようなプログラムを作成しようと思ったときにすごく便利なライブラリにMechanizeというものがあるのですが、、このmechanizeを用いるとメタタグに文字エンコーディングが記述されていないような一部の日本語のページで文字化けが発生する場合があります。

この事象は下記のページに詳しく記述されているのですが、

RubyのMechanizeで文字化けするページがある件について
http://insideflag.blogspot.com/2010/06/rubymechanize.html

どうもMechanizeのエンコーディングの決定方法と内部パーサーのNokogiri(libxml2)の問題で結構根が深いようでした。

いろいろ試してみたのですが、どうも上手くいかなくて前に作っていたプログラムはHTMLパーサーをhpricotに変更して回避していました。(hpricotは文字化けしない)

んで早速、同じようにhpricotに変更しようとソースなどを修正していると、どうもうまくいかない?

前のコードでは動いたのに、最新のMechanizeではデフォルトのHTMLパーサーをhpricotに変更できていないみたい。

前に動いていたMechanizeのバージョンが0.9で今最新版は2.0.1なので設定方法に問題があるのかといろいろやった結果。

すごくシンプルに以下のようにするとでけた。


--
#! /usr/bin/ruby
# -*- coding: utf-8 -*-
#
# Mechanizeでhpricotを使う
#
$KCODE = 'u'
require 'rubygems'
require 'mechanize'
require 'hpricot'
require 'kconv'

# サンプル
def main()
# URL
url = 'http://blog.livedoor.jp/geek/'

# agentを初期化
agent = Mechanize.new

# URLに接続
page = agent.get(url)

# pageオブジェクトをHpricotに渡してパーズする
doc = Hpricot(page.body)

# タイトルを表示
puts (doc/"title")[0].inner_html.toutf8
end # main

# main 関数
if __FILE__ == $0
main()
end
--
$ ./ex.rb
アキバBlog(秋葉原ブログ)


なんかすごい小難しいことを考えていたけど、、単純にpageオブジェクトをHpricotに渡せばいいだけ。

なんか、ドアの鍵とかいろんな手段でなんとか開けようと努力していたんだけど、、結局、ドアの鍵があいていて正面から入れたような気分。

とりあえず、これでも日本語のページも文字化けせずに取得できるようになったぉ。
[ Ruby ] twitter スパム推定(判定)の新素性(ツィート類似度)
2011.10.01 (09:45) プログラミングtrackback(0)comment(0)
Twitterでつぶやく
a4967e36.jpg


先日から,twitter bot(@tachi_pic_bot)にtwitter スパム推定(判定)機能を作っていて、実際に搭載までできたのですが、もう少しtwitterのスパム推定機能について強化というか研究してみた。

このスパム推定はtwitterアカウントの情報を抽出し、それを素性としてサポートベクターマシン(SVM)で学習/推定しておきます。判定精度は90%以上を実現しているのですが、論文を読んでいると面白そうな素性があったので追加してみました。

スパム判定用に追加した素性は"ツィート類似度"というもの。「スパムアカウントはいつも同じような文言をつぶやるよね?」という想定で作った素性です。もちろん、本文中の@user_name
やURL情報は予めストップワードとして削除しきます。

以下の論文で紹介されていたのですが

DON’T FOLLOW ME: SPAM DETECTION IN TWITTER Alex Hai Wang

ちょっと分かりにくいものだったのでわかりやすく、整理してツィート類似度を以下の式で定義します。

sim.png


ここでNは取得できたツィート総数でTwiter APIを利用すると通常は直近の20ツィートが取得できますので、だいたいはN=20となります。strが1つのツィート文字列,lsdは文字列i,文字列jのレーベンシュタイン距離を算出する関数になります。

この素性はツィートしていた内容ば全て同じであれば類似度は1.0になり、ツィート内容に一致する文字列がない場合は0.0になる素性となっております。

簡単な式ですが、システムなんかにのってしまうと結構こんなんでも特許になりますよね。www

最初にこの素性の生データを確認しておきます。赤色がスパムアカウントから抽出した素性、青色が通常のアカウントから抽出した素性です。


tweet_sim_fog.png


スパムと比スパムの事例は完全には分離できていないですが、最初の目標通り、スパムアカウントの多くは同じような内容のツィートをしている傾向が強いようです。

この新しい素性を入れて3分割交差検定で評価した結果、いままでのベストパラメーターの推定結果と比較すると以下のような感じ。

# BEST
97.278 [%]

# ツィート類似度を追加
96.825 [%]

となって1[%]ほど精度が低くなってしまいました?toro_mune.gif

なんでかなぁ~と思ったので、他の素性のデータを見て見ることにします。

●Friend Count(フローしている人の数)
friend_count.png



●Followers Count(フローされている人数)
followers_count.png


これらの素性はツィッターを特徴付ける素性ですが、スパムと比スパムとの事例では差はほとんどないことがわかりますな。

●Twitter Follower-Friend Ratio(フォロワー数をフォロー数で割ったもの)
ff_ratio.png


ここまでするとかなり、それっぽくスパムと比スパムが分かれてきておりますな。このような素性を使った場合の精度は90%程度になり、もう少しな感じです。

●Listed Count(他人のリストに入っている個数)
listed_count.png


●Listed ratio(他人のリストに入っている個数をフォローさわている数で割ったもの)
listed_ratio.png


これらの素性が優秀すぎんじゃん。もうSVMとかいらないレベル!!!

これらの素性が強すぎてこれらを入れたあとに他の素性を追加するとノイズになって逆に精度が低下してるように思います。一応、listed系を抜いてからツィート類似度の素性を入れて学習すると1[%]程度は上がることはあがるので、有効性はあるといえばある、、、

今度は素性選択ができるようにしようと、、
[Ruby] DON’T FOLLOW ME ( Twitter スパム推定の結果)
2011.09.29 (11:17) プログラミングtrackback(0)comment(0)
Twitterでつぶやく
mnys1.jpg


作成したtwitter bot(@tachi_pic_bot)が明らかに中の人が人間じゃない人にフォローされていて、自動化としてはフォローされた人は無作為にこっちからフォローしていたのですが、、ちょっと賢くしてbotにスパム推定機能をつけようじゃないかという開発で、とりあえず、botに実装完了。

botをフォローしてくださっている方を全て一度、スパム推定を実施。

結果は以下のような感じで、スパム推定したのは297事例でそのうち、59事例が比スパムという結果になりました。
約20%がスパム判定されたということになります。


follow.png


実際には結構厳しめの設定なので誤判定でスパムに判定されているケースもあるかと思いますが、、整理し終わったあとで比スパムの事例を見るとそれなりにおかしくない結果(中の人がリアルに書いていて、広告でもアダルトでもない)事例が多く残っているので機能としては結構できている感があるとこまでいけました!!

あとは継続的に回せるように幾つかの仕組みを実装したり、新素性を入れてみて精度を測ってみたりしようかと思っておりますな。とりあえず、成功かな。
homenext
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。