Reports

Twitter: @mtknnktm.

JRIを使ってScalaからRを使う

RをScalaから叩く方法をメモ。
JavaからRを使う Java R Interface (JRI) というライブラリを使用します。

試した環境

  • バージョン
    • Scala: 2.10
    • SBT: 0.13.0
    • R: 3.0.2
    • OSはMac

Rの準備

まず環境変数 R_HOME を設定します。
Macの場合は以下みたいになると思います。

export R_HOME=/opt/local/Library/Frameworks/R.framework/Resources

次にJRIはRからJavaを使うパッケージ rJava についてくるので、まずRに rJava をインストールします。

install.packages('rJava')

rJavaをインストールするとMacだと /Users//Library/R/3.0/library/rJava/jri

  • JRI.jar
  • libjri.jnilib

があるので、それをScalaプロジェクトの lib 以下にコピーします(http://scalajp.github.io/sbt-getting-started-guide-ja/library-dependencies/)。

Scala

JRIにパスを通すためにbuild.sbtに以下を追記します。

javaOptions in run += "-Djava.library.path=" + System.getProperty("java.library.path") + ":lib"

これで環境は整ったはずなのでScalaからRを使ってみましょう。
App.scalaを以下のようにします。

import org.rosuda.JRI.{ REXP, Rengine }

object App {
  def main(args: Array[String]) {

    val engine = new Rengine(Array("--no-save"), false, null)
    val result = engine.eval("sum(c(1, 2, 3, 4))")
    engine.end()
    println(result.asDouble)
  }
}

以上が完了したら以下を実行して 10 と表示されたら成功です。

sbt run

以下のページを参考にしました

SBT

Forking — sbt Documentation

Scala逆引きレシピ

Scala逆引きレシピ

RとRubyによるデータ解析入門

RとRubyによるデータ解析入門


「いいね」はなぜ簡単でいいのか?

はじめに

Facebookの「いいね」に代表されるような "各ユーザの投稿・行動に対して1クリックという簡単な動作で「私はあなたの投稿(行動)に好感を持ちました」というポジティブな感想を伝える機能" は最近のSNSに多く実装されている。この機能は投稿者にポジティブなフィードバックが発生しやすく、かつ、読み手にとっては非常に簡単に実行できるため、SNSへの投稿を活性化させる素晴らしい発明であると言えよう。そのため「いいね」が適切なタイミングで適切な量行われる場合、投稿者と読み手の間にシンプルだがコミュニケーションが活性化し、両者の繋がり(やや大袈裟に言うと仲間意識)は強くなっていくであろう。一方で、簡単であるがゆえに読み手は「いいね」を乱発することも簡単で、例えば友達の投稿全てに「いいね」をすることもできる。もちろんそうなった場合、その「いいね」の価値は低くなり、コミュニケーションとしてもほとんど意味のないものになる。

ここで、この「いいね」の仲間意識を強めるコミュニケーションという側面について考える。このようなコミュニケーションはヒト以外でもされており、例えばチンパンジーなどの類人猿ではグルーミング(毛づくろい)がそれに対応する。すなわち、グルーミングは単に体からノミなどを取り病気を防ぐだけでなく、お互いの協力関係や序列(どちらがより上位か)を確認し、確立する行為でもある(グルーミング - Wikipedia)。こういった行為を社会的グルーミングと言う(本記事では毛づくろいという行為にかかわらず社会的に同様の意味を持つ行為をグルーミングと呼ぶ)。おそらく我々ヒトの祖先もこのように社会的グルーミングをして互いの仲間関係・上下関係を確認し合い、社会関係を作り上げていったのであろう。

しかし、ヒトの社会では付き合いのある相手全てに対して毛づくろいのような時間や手間のかかるグルーミングをすることはできない(チンパンジーの集団(50体ぐらいの群)に比べ、原始のヒトの集団は150人ぐらい(11 - On the origin of the human mind - University Publishing Online)と集団サイズが大きい)。そのため、毛づくろいより簡単な「視線によるグルーミング」が進化したと考えられている(The gaze that grooms: contribution of social factors to the evolution of primate eye morphology)。この研究では、ヒトを含む霊長類において視線の追いやすさと社会性(新皮質の大きさや群のサイズ)に関連があることを示し、視線によるグルーミングが様々な霊長類で行われていること、視線の追いやすさ(グルーミングのしやすさ)は社会的状況に依存して変化したことを示した。

例えば、チンパンジーを含め多くの霊長類は、顔が黒く、強膜(いわゆる白目)も黒く、瞳孔(黒目)も黒いため、よく見ないとどちらを見ているかわかりにくい。これは視線はコミュニケーションの道具である一方、他者に視線の方向を悟られることが不利になる(自分の見つけた食べ物を横取りされる)ため、このように進化したと考えられる。一方でヒトは、顔の色は様々で、強膜は白く、瞳孔は黒い(おまけにとても横長の瞳)ため、相手がどちらを見ているかが非常にわかりやすく、相手に「視線の方向を悟らせるため」の目をしている。

前述のようにグルーミングは高コストなものであるほど、その効果は高いが、コストが高い分だけ少人数相手にしか実行できず、低コストであるほど、その効果は低いものの多くの人数相手に実行可能であり、それぞれ有効な社会的状況は異なる。人間社会で例えるならば、高コストなグルーミングはお歳暮や義理チョコなどで、低コストなグルーミングは「いいね」などであろう。

では、どんなときにどれだけのコストをグルーミングに掛ければいいのか? 言い換えると「いいね」は「どんな社会的状況」ならば効果を持つのか? その逆の高コストなグルーミングは「どんな社会的状況」に有効なのか? 本記事ではこの疑問について考えるためにシンプルなモデルによる数値シミュレーションでアプローチする。

モデル

N 個体の集団がグルーミングで仲間関係を形成(グルーミングフェイズ)し、その後にグルーミングで築いた関係を用いて囚人のジレンマゲームをプレイ(ゲームフェイズ)するという状況を考える。この2つのフェイズを経て各個体が得た適応度を元に集団を進化させる。

グルーミングフェイズ

このフェイズでは各個体が他の個体に対してグルーミングをする。各個体 i のグルーミングする相手の数は

 (N - 1) r_i (1 - c_i) … ①

で決まり、集団中からランダムに選んでグルーミングをする。ここで  r_i \in [0, 1] は個体 i のグルーミング率と言い、自分以外の全個体( N - 1)に対してどの程度グルーミングしようとするかを表す。  c_i は個体 i のグルーミングに掛けるコストを表し、 c_i \in [0, 1] が高ければ高いほどグルーミング可能な相手は減るとする。

個体 i が個体 j からグルーミングされた場合、個体 i は個体 j に対して信頼度  b_{ij} \in [0, 1]を得る。信頼度はグルーミングのコストに比例する( b_{ij} = c_j)とする。

このようにして全個体は他の個体に対してグルーミングをし合う。

ゲームフェイズ

このフェイズでは各個体が他の個体と囚人のジレンマゲームをする。利得行列は以下とする。

協調 裏切り
協調 3, 3 0, 5
裏切り 5, 0 1, 1

N個体の集団から一つ個体を取り出し、この個体 i が他の全個体とゲームをする。この時、起点となる個体 i をホスト個体と呼び、それ以外の個体をゲスト個体と呼ぶ。ホスト個体 i は自分がグルーミングした相手であれば協調、そうでなければ裏切り戦略を選択する。ゲスト個体 j は個体 i に対する信頼度  b_{ij} を評価して基準を満たしていれば協調、そうでなければ裏切り戦略を選択する。 具体的には自分にグルーミングをした全個体に対する信頼度  b_{*j} のうち、信頼度の高さが上位 R 位以内であれば協調、そうでなければ裏切るとする。この R はゲストの時の協調ができる回数であるため、環境の状態と解釈できる。つまり、R が N - 1 に近い場合は、(一般にコストの高いと言える)協調行動が他の全ての個体に対して可能なので、資源が豊富な環境であると言える。一方で R が 1 に近い場合は、協調行動が信頼度の高い数個体相手にしか協調行動ができないので、資源の少ない厳しい環境であると言える。

このようにして全個体が1回だけホストになり、また、N - 1 回だけ他個体のゲストになり、ゲームをし合う。その結果、各個体 i の利得の合計を  P_i とすると、その個体の適応度  f_i

 f_i = P_i - (N - 1)^2 c_i r_i … ②

とする。ここで  (N - 1)^2 c_i r_i は、グルーミングにリソースを割いたことに対するコストであり、グルーミングをすればするほど、グルーミングにコストをかければ掛けるほど適応度が下がることを表す。

進化

上記の2つのフェイズを経て各個体が得た適応度を元に集団を進化させる。進化対象の個体の属性はグルーミング率 r とグルーミングコスト c の2つである。

2つのフェイズ終了後、適応度 f における上位 S 個体の属性 r と c はそのまま次の世代に受け継がれる。加えて、上位の S 個体の更に上位 N - S 個体の r と c を ± 0.1の範囲で突然変異をさせ、次の世代とする(ただし r, c \in [0, 1] は満たすように境界値を処理する)。このようにして、今の世代の N 個体から次の世代の N 個体を生成する。

本記事の目的は進化ダイナミクスについて知ることが目的ではないが、各個体のグルーミングに関する属性(r と c)の進化(や学習)によって集団全体が安定的に釣り合いっている状態(平衡点)を求めるために使用する。

数値シミュレーション

上記のモデルを使用して数値シミュレーションを行う。集団の個体数 N = 100、選択個体数 S は 80とする。初期世代の r と c は  [0, 1] の範囲でランダムに与える。

このような設定で任意の R を設定して、200世代の進化をさせ、その時の r と c を観測した。

以下にグルーミングの進化(r と c)に対する R の影響を示す。R は 0 から N まで 5 刻みでそれぞれ設定している。

f:id:swarm_of_trials:20130715123932p:plain

同図から R が 0 の場合は、ゲストが誰とも協調行動をしないため、当然、グルーミングは進化しなかった。

R が 0 より少し大きい領域( 0 < R \leq 15)では、 R に比例してグルーミング率 r が大きくなり、また、コスト c も増加したため、集団のごく一部の相手に対して少しだけコストを掛けるようなグルーミングをする集団に進化したと言える。これはグルーミングをしても、ゲストが協調可能な相手数 R が少ないため、グルーミングをして相手の協調行動を期待するよりもグルーミングによる適応度低下を防ぐ方が適応的だったためと考えられる。

さらに R が大きい領域( 15 < R \leq 50)では、r はさらに増加したが、c は 0.5 程度とほぼ一定(本シミュレーションでは最大)になり、集団中のそれなりの数の相手に対して、かなりのコストを掛けてグルーミングをする集団に進化した。例えば R=40 の場合では、グルーミングの相手数は式①より、 (N - 1) r_i (1 - c_i) = (100 - 1) 0.8 (1 - 0.5) = 39.6 となり、各個体はおよそ40個体程度相手にグルーミングをしている。これは、ゲストが協調可能な相手数 R がある程度あるため、グルーミングをすれば相手の協調行動が期待できるものの、R は全体の半分以下と限定的であるため、相手から高い信頼度 b を得る必要があったためと考えられる。

より R が大きい領域( 50 < R \leq 100)では、他と大きく異なり、r はほぼ最大値 1 に近くなり、c は R に対応して減少した。これはゲストが協調可能な相手数 R が多いため、グルーミングにより適応度低下より、薄く広くグルーミングをして相手の協調を期待するように進化したと考えられる。R が大きいほど、グルーミングにコストを掛けなくても相手は協調しやすくなるので、R に対応して減少したと考えられる。

まとめ

毛づくろいのような高コストなグルーミング行動や「いいね」のような低コストなグルーミング行動について、それぞれどんな状況ならばどのように成立しうるかについて考察するために、囚人のジレンマゲームで協調をするための信頼関係を築くためにグルーミングをするというモデルを構築し、それの進化シミュレーションをして平衡状態を求め、それの分析を行った。

その結果、協調行動のコストが高く可能な協調行動の回数が限られるような厳しい環境下では、対象の相手から「他の人より自分が高い信頼を得る必要が有る」ため、一部の相手を対象とした高コストなグルーミングのみ成立しうること、逆に、協調行動のコストが低く誰に対しても協調行動ができるような余裕のある環境下では、浅く広い信頼関係が有効であるため、大部分の相手を対象とした低コストなグルーミングが成立することがわかった。そしてこの2つの状態は環境によって明確に区別され、相転移や分岐のようにも見える。この臨界点の存在については別途数理解析をしたい。

おそらくヒト(もしかしたらチンパンジーなどの類人猿も)は、相手にして貰いたい協調行動のコストに応じて様々なコストのグルーミングを(意識的/無意識的に)使い分けているのであろう。いつ、どんな社会的状況でどんなコストを掛けたグルーミングをしているか? の実際の振る舞いについては、Facebookなどのデータを利用した分析を今後の課題としたい。めったに「いいね」しない人としょっちゅう「いいね」する人の「いいね」の効果の違いや、「いいね」とコメントでの「おめでとう!」といった定型文、相手の状況に合わせたコメントといった違いの考察などである。

ソーシャル・ネットワーク (字幕版)

ソーシャル・ネットワーク (字幕版)

Pixivの北斗の拳のイラストのタグ情報についてアソシエーション分析してみた

はじめに

アソシエーション分析とは、ある項目Aが出現する場合に項目Bも出現するという項目の関連性を表すルール(相関ルール)を抽出して分析するテクニックです。
このAは条件部、Bは結論部と呼ばれます。また元となるデータの1つ1つはトランザクションと呼ばれます。
この記事ではPixivのイラストに付けられたタグ情報についてアソシエーション分析をします。
1つのイラストに付けられたタグのまとまりをトランザクションとし、あるタグがそのトランザクション中に出現した場合、どのようなタグが一緒に出現しやすいかというルールを見ていきます。
ちなみにアソシエーション分析は、小売店の買い物カゴに一緒に入れられて購入された商品の組み合わせを理解することによく使われるため、バスケット分析とも呼ばれています。

というわけでイラストのタグについてアソシエーション分析をすると「どんなタグが同時に付けられているか?」がわかります。
今回は北斗の拳のイラストにおいて、どのキャラクターがどんな組み合わせで描かれているか?調べてみます。

イラスト情報取得(Ruby

まずPixivのイラスト情報を取得します。
APIの叩き方や詳細については以下のページを参考にしました。

# -*- encoding: utf-8 -*-

require 'httpclient'

hc = HTTPClient.new

tag = "北斗の拳" #検索タグ
maxp = 50 #取得したい最大ページ

# PHPSESSIDを入れる。pixivのajaxリクエストのリクエストパラメータを漁ればどこかにある。
# 無効な値を入れても値は取得できるが、その場合は数ページしか取得できない
id = "PHPSESSID" 

for page in 1..maxp do
  csv = hc.get_content("http://spapi.pixiv.net/iphone/search.php?s_mode=s_tag", "p" => page, "word" => tag, "PHPSESSID" => id)
  csv = csv.gsub(/,\n/, "\n") #最後にカンマが付いているので除去
  print csv
  sleep(1) #ちょっと気を使ってみる
end

アソシエーション分析(R)

上記でダウンロードしたイラスト情報のタグについてアソシエーション分析をしてみます。
以下のcharas.txtは、キャラクターのタグについてのみ分析したいので、キャラクターを抜き出すためにキャラクタ名一覧を保存してあるファイルです。
Wikipedia北斗の拳の登場人物一覧から作成しました。

library('arules')

# キャラクタ名の読み込み
charas <- unique(read.table('charas.txt'))
names(charas) <- c('full')

# ダウンロードしたイラスト情報を読み込んでタグ情報のみ抜き出し
pic_data <- read.table('pixiv_hokuto.csv', sep=',')
tags_data <- data.frame(pic_data$V14)
names(tags_data) <- c('base')

tags_data$tags <- apply(tags_data, 1, function(row){
  tags <- c()
  base <- data.frame(strsplit(row['base'], "[ _-]"))
  names(base) <- c('tag')
  # 各イラスト情報について各キャラクタ名が含まれているか1つずつ調べる。
  # あまりいいやり方じゃない(´・ω・`) というか無駄にすっごい重い
  for(n in charas$full){
    if(length(subset(base, tag == n)$tag) > 0){
      tags <- c(tags, n)
    }
  }
  if(length(tags) > 0){
    tags
  }else{
    NULL
  }
})

tran <- as(as.list(tags_data$tags), 'transactions')

# 出現頻度(support)が0.005 (0.5%) 以上の組み合わせを対象とします。
ap <- apriori(tran, parameter = list(support=0.005,confidence=0.01, maxlen=5))

# 結果をソートしてLift順に表示
inspect(head(sort(ap, by = 'lift'), 30))

以下が実行結果です。

1  {リン}       => {バット}      0.0084 0.47727273 25.9387352
2  {バット}     => {リン}        0.0084 0.45652174 25.9387352
3  {サウザー,                                                
    レイ}       => {シン}        0.0060 0.68181818 16.5489850
4  {リュウガ}   => {ジュウザ}    0.0072 0.30508475 13.6198547
5  {ジュウザ}   => {リュウガ}    0.0072 0.32142857 13.6198547
6  {シン,                                                    
    レイ}       => {ユダ}        0.0064 0.59259259 11.4843526
7  {シン,                                                    
    ユダ}       => {レイ}        0.0064 0.69565217 10.7353731
8  {ケンシロウ,                                              
    ジャギ,                                                  
    トキ}       => {ラオウ}      0.0108 0.96428571 10.0866707
9  {シン,                                                    
    レイ}       => {サウザー}    0.0060 0.55555556  8.4688347
10 {ケンシロウ,                                              
    ジャギ,                                                  
    ラオウ}     => {トキ}        0.0108 0.93103448  8.3426029
11 {サウザー,                                                
    シン}       => {レイ}        0.0060 0.53571429  8.2671958
12 {ユダ,                                                    
    レイ}       => {シン}        0.0064 0.34042553  8.2627556
13 {ケンシロウ,                                              
    トキ}       => {ラオウ}      0.0152 0.73076923  7.6440296
14 {ジャギ,                                                  
    トキ,                                                    
    ラオウ}     => {ケンシロウ}  0.0108 0.93103448  7.5817140
15 {ケンシロウ,                                              
    トキ,                                                    
    ラオウ}     => {ジャギ}      0.0108 0.71052632  6.7798313
16 {ケンシロウ,                                              
    ジャギ}     => {ラオウ}      0.0116 0.64444444  6.7410507
17 {ジャギ,                                                  
    ラオウ}     => {トキ}        0.0116 0.72500000  6.4964158
18 {ジャギ,                                                  
    トキ}       => {ラオウ}      0.0116 0.58000000  6.0669456
19 {ジャギ,                                                  
    ラオウ}     => {ケンシロウ}  0.0116 0.72500000  5.9039088
20 {ユダ}       => {レイ}        0.0188 0.36434109  5.6225476
21 {レイ}       => {ユダ}        0.0188 0.29012346  5.6225476
22 {ケンシロウ,                                              
    ラオウ}     => {トキ}        0.0152 0.62295082  5.5819966
23 {ケンシロウ,                                              
    ジャギ}     => {トキ}        0.0112 0.62222222  5.5754679
24 {トキ,                                                    
    ラオウ}     => {ケンシロウ}  0.0152 0.64406780  5.2448518
25 {ケンシロウ,                                              
    トキ}       => {ジャギ}      0.0112 0.53846154  5.1379918
26 {マミヤ}     => {レイ}        0.0084 0.31818182  4.9102132
27 {レイ}       => {マミヤ}      0.0084 0.12962963  4.9102132
28 {トキ,                                                    
    ラオウ}     => {ジャギ}      0.0116 0.49152542  4.6901281
29 {ジャギ,                                                  
    トキ}       => {ケンシロウ}  0.0112 0.56000000  4.5602606
30 {ケンシロウ,                                              
    ラオウ}     => {ジャギ}      0.0116 0.47540984  4.5363534

見方ですが、例えば以下のケンシロウ・ジャギ・ラオウの例だと、

   lhs             rhs          support confidence      lift
6  {ケンシロウ,                                             
    ジャギ}     => {ラオウ}      0.0116  0.6444444  6.741051
  • ケンシロウとジャギがタグ付けされ、かつ、ラオウもタグ付けされる場合は 1.16% (support)
  • ケンシロウとジャギがタグ付けされた場合の内、ラオウも同時にタグ付けされている割合は 64.44% (confidence)
  • リフト値(lift)は「ラオウがタグ付けされている場合」に対して「ケンシロウとジャギがタグ付けされ、かつ、ラオウもタグ付けされる場合」はどの程度よく現れるか?を表します(ほとんどのイラストにラオウがタグ付けされていればこの値は小さく、ケンシロウとジャギがタグ付けされているイラストのみにラオウがタグ付けされていればこの値は大きくなります)


それで、上記の結果をみてみるとリフト値が高い組み合わせのトップはリンとバットでした。
出現頻度(support)はそんなに高くないので、タグ付け頻度はそんなに高くないけど、出てくるときは大抵セットということです。
次いで、サウザー・レイ・シン、リュウガ・ジュウザになっています。
シンって本編でこの2人と絡んでましたっけ…情報求ム!
その次がシン・レイ・ユダ様と他の南斗とほとんど絡みのないシンに妙に人気が集まっています
次いで北斗四兄弟です。
北斗四兄弟の組み合わせは出現頻度は全体的に高めですが、それぞれ独立にタグ付けされることも多いのでリフト値はなかなか大きくならないようです。

全体的に割りと順当な気がしますが、シンがあまり絡みの無かった南斗系にいろんな組み合わせで出てくるのが以外でした。
あと、アミバ・トキはもっと上位に来ると思ってたんですがそうでも無かったです(表示件数を増やしてやると出てきます)。

まとめ

というわけで、Pixivの北斗の拳のイラストのタグ情報についてアソシエーション分析をしてみました。
その結果、どんな組み合わせのキャラクターがどんなふうにタグ付されているかを定量的に見ることが出来ました。
色々試してみたら意外な組み合わせが発見できるかもしれません。


富・収入・支出分布が気になった

はじめに

富の分布はべき分布に従うことは広く知られています。
べき分布はべき指数で特徴づけられます。

ってことで、簡単にググって見つかったものをメモ。
論文は見ただけ(まだ読んでない)です。

富や収入は結構探せば有りそうだけど支出のデータってあんまり無さ気。

富・収入
  • Income and Poverty in a Developing Economy
  • An out-of-equilibrium model of the distributions of wealth
支出
  • 1人あたりの支出額と規模の経済
    • 分布の形状は対数正規分布。なぜ対数正規分布になるかは言及されてない。
      • p. 23
    • 支出額の測定方法(p. 5)
      • 1 ヶ月の支出額(合計)は、以降の分析モデルにおける被説明変数となる。1 ヶ月の支出額は、2009 年 1 月の 1 ヶ月間に世帯全体で支出した金額を尋ねたものである。この設問では、対象者が 1 ヶ月の支出額を費目別に回答したのちに、「合計」を回答するように設計されている。そこで回答された合計額を、本稿の分析で用いる。
    • http://www.pdrc.keio.ac.jp/2010-001.pdf

歴史は「べき乗則」で動く――種の絶滅から戦争までを読み解く複雑系科学 (ハヤカワ文庫NF―数理を愉しむシリーズ)

歴史は「べき乗則」で動く――種の絶滅から戦争までを読み解く複雑系科学 (ハヤカワ文庫NF―数理を愉しむシリーズ)

明日をどこまで計算できるか?――「予測する科学」の歴史と可能性

明日をどこまで計算できるか?――「予測する科学」の歴史と可能性



洋書EPUBの辞書設定を英英辞書から和英辞書に変更する

  • EPUBではその書籍についてどの言語の辞書を使うかを opfファイルの dc:language というメタデータで書籍ごとに制御してるっぽいです。
  • そしてたいていの洋書は英語圏の人が買うので当然、英英辞書に設定されていることが多いです。
  • 私は洋書読むのに和英辞書が必須なので、和英辞書がつかたいのですということでメモ。
    • とりあえずオライリーで買った洋書は以下の方法でやって、iBooksで和英辞書が表示されるようになりました。
  • 注)EPUBファイルが壊れる可能性があるので自己責任でお願いします。
  • epubDcJa.sh
#!/bin/bash

# バックアップを取って解凍
cp $1.epub $1.org.epub
unzip $1.epub -d $1

# dc:language要素の値をen(英語)からja(日本語に変更)
sed -i 's|en</dc:language>|ja</dc:language>|g' $1/OEBPS/content.opf 

# EPUBだとmimetypeファイルは非圧縮・ファイルの先頭の必要があるので、先にmimetypeのみepubに追加
zip -0 -X $1.epub $1/mimetype

# 残りのファイルをepubに追加
zip -r $1.epub $1/* -x mimetype
  • 以下、実行方法
% epubDcJa.sh english.epub


HTML5 Conference 2012メモ

  • ひたすらメモっただけ。

基調講演 - Web技術の過去・現在・未来(及川さん、白石さん)

  • 2004
  • 2007, 2008
    • GDD: Google Gears → アプリ用の道具(API
      • Gearsは標準化への準備・試しの実装
      • Webのアプリ化に耐えられるブラウザ - Chrome
  • 2009
    • GDD: HTML5普及促進を明言
  • 2010
    • AppleFlash 非サポートを明言。すべてをHTML5へ、という方針。
  • 2011
    • 最新ブラウザの普及率向上
  • 2012
    • Canvasなどからよりリッチに: WebGL, Device Access, Offline Access, WebIntents, Native Client, JS and DOM, WebRTC, Web Audio API
  • past - now
    • できなかったことをできるように。ネイティブに追いつくように
  • now - future
    • 妥協無く動くように
    • より簡単に実現できるように
      • WebIntents: アプリ間連携
      • WebComponents: DOMを部品化 //これは熱い!
  • ブラウザとは
    • もはやインターネット閲覧ソフトではない
    • クラウドアプリケーションのフロントエンド
    • いろんなデバイス(ロボットとか)がクラウドにつながる
      • → ブラウザは常に存在するコントローラにも
  • HTML5のこれから: 拡がる可能性・複雑化する技術・安全/安心への責任
感想
  • "安全/安心への責任" という一言が一番印象に残った。
  • もう "新しいことができるようになって楽しい" というフェイズではなく、ちゃんとしたシステムづくりの一環になるとだと再認識。

Webプラットフォームの進化と実装 〜Web技術の現在と未来〜(浅井智也)

  • HTML5への期待
    • 次世代プラットフォーム
      • マルチデバイス(スマフォ、タブレット、PC)で高度なアプリ開発・組版(レイアウト)技術
  • html5: バラバラだった機能を拡張・標準化、組版(CSS3)の向上
    • → これから: デバイス連携、
  • html5という仕様はもう古い(標準化は時間がかかる)(W3C
  • Working Groupでより新しいことを
  • 既存の独自プラットフォーム
    • iOS, Android, FB, Chrome(単独ベンダ)
    • VS Web プラットフォーム
    • オープンなWebプラットフォームでいきたい
  • ほんとに可能か?
  • win8: メトロ。htmlは形式的に使うだけ。div祭り & 独自data属性が多い。JS APIも独自
    • 無理に合わせてるだけなので使いにくいし、使い回しできない。
    • しかもIE10とメトロは非互換(´・ω・`)
    • セキュリティ上の制限も違う
    • 非常に拡張されているので便利といえば便利
    • windows store: UIガイドが厳しい。Webアプリ読み込みだけというのは不可
    • 囲い込みが強いように見える。
    • Webと違うならHTML使う意味ない。
  • Firefox OS
    • Webがネイティブ
    • アプリ開発はHTMLのみ。OSのUIも全部HTML。
    • 実装と並行して標準化
    • Webアプリがそのまま動く(PC・スマフォ同じ)。セキュリティモデルは同じ。
  • iOS
    • ネイティブ限定
    • 独自ブラウザエンジンは不可
    • WebViewは可
      • JIT無効の低速JS(Mobile Safariよりかなり遅い)
      • 機能制限が強い
  • Android
    • ネイティブ限定
    • 独自ブラウザエンジンは不可
    • 制限もなし
    • WebViewも可
  • Webでは出なかったこと
    • システムステータス(通信方式、wifiのon/off)
    • センサー
    • 低レベルH/W制御(USB/NFC/BlueTooth
    • このへんMozillaがんばってますよ
      • モバイルがWebに向かっていない → Webをモバイルに。
  • FirefoxOS(android端末とかにインストール可)
    • カーネルの上にWeb Engineが直で乗ってる(・∀・)
    • すべてWeb技術で。アイコンとかもCSS
    • 発展途上国でも売れる値段で提供できるようにする(H/Wベンダと組んでる)
  • デスクトップアプリもWeb技術で。
    • ブラウザの枠に縛られない、Webアプリ。
  • IDEは用意する?
    • 純粋なWebアプリなので不要。MozillaにはAdobeが協力表明をしている。
感想
  • 「Pure HTML5 で行く。そうでなければWebは発展しない。」というMozillaのビジョンがよくわかった。
  • 確かにWindows 8のように中途半端にHTML5を採用しても余計に大変になるだけだと思うし、その煽りを食らいそうでいまからガクブルしている…

WebIntentsにより拓かれる次のWeb(小松健作)

  • 資料: 探し中
  • Webはクラウドだけではない
    • デモ: webからテレビを操作する
  • カメラ、テレビ、etc… も全部Webにつながる
  • クラウドもローカルも全部Web
    • 全部シームレスに普通に使えるように
  • Webアプリ同士をつなげる仕組み
  • Android のインテンツとよく似ている
  • ユーザがこのアプリこういうふうに使いたい(名詞・動詞のペア)
    • e.g.: Twitter (Facebook) で記事をシェアしたい
    • registration & invokeで実現
  • regiastration(Twitter がブラウザに宣言)
    • 「何(名詞: mine-type)」に対して「これ(動詞: share, view, edit, etc…)」ができる と宣言
    • htmlにタグを書く。
      • プラウザが対応していれば登録される)
      • chrome extensionでmanifestファイルでも宣言できる
  • invoke
    • アプリからjsで実施し、registrationされたアプリ(twitter)を呼び出す
      • Device API -> in-device Web Server Model
  • 2つのWGが関わっている
    • オープンにしなければならないが、特許に抵触するためあまり実装がされていない
    • → デバイスがローカルにWebサーバを持ち、そこにむかってAPIを叩く形で連携する
  • サービス選択の自由
    • どのサービスを使用するかはユーザの自由
    • 状況にあわせて選択する(公/私とか)

  • 検索のモデルがWebアプリにマッチしていないのではないか?
    • 使いたい時に連携しているアプリの情報をだすようにしたい
  • local network devicesへの拡張
    • そもそも必要?→実はすでに組み込まれている
    • DLNA - SOAP: TVなどのデバイスをリモート操作
    • UPnP: IP multicastを行い自動発見
    • → JSから叩いてやれば操作可能。普通のTVでもブラウザからAPIを叩くことで可能。
    • クラウドもローカルもシームレスに繋ぐことができる!!1
    • 限定的な状況なら実現可能。すぐそこの未来。W3Cで検討中。
感想
  • デバイス類がシームレスに連結してシステムとして動作するというのは、システム屋としてたまらない未来。
  • そうなるとPure HTML5でほとんどのことができるということが非常に重要になってくると思う。
  • すでに受け手としてのTVにはその準備ができていることが意外で、某スマホクラウド洗濯機も壮大なビジョンに基づいた一手なのではないかと勝手に妄想w

Web最先端、エキスパートたちの視点から(白石さん、小松さん、羽田野さん、及川さん、新野さん)

振り返り
  • ここ数年で変わったところ
    • 白石: 2009年 - html5j 立ち上げ。その頃はここまで波が来るとは思わなかった。
      • 新野: MS/AdobeHTML5は無視/軽視してた状態だった
    • 小松: すごいものだと思ったが、仕事でR&Dでやることになるとは思わなかった。
    • 羽田野: html5.jp は5年前に立ち上げ。誰も注目してなかった。
      • web業界以外の人たちがHTMLに注目している点がこれまでのHTMLと違う点
      • 注目されてきた点: Canvas/映像や音-> Device
    • 及川: Chrome立ち上げ。最初はなぜgoogleがそんなものを。とも思ったが、あれがまさにWebの起爆剤になった。
Webの成功
  • Flashなどの強力な競合があったにもかかわらずなぜHTML5がここまでになったか?
    • 及川: 開発者・ユーザが勝手に作って、それが標準に取り入れられていった、オープンなプロセスがあったから。今後もどんどん変わっていくと思う。そしてもっといろんな分野に適用されていき、どんどん変わっていくと思う。
      • スマフォがwebkitのみだったから(実際は差があるが)。画像を使わずにCSSで軽量なページが開発ができるようになったから。
    • 新野: 新しく出てきたときは基本的に貧弱。それを皆で成長させていくプロセスが面白いと思う。
    • 羽田野: 1.(冷めた言い方をすると)Apple。2. ベンダのコントロールを受けずにビジネスができるから。
    • 小松: これまであったブラウザで急速にできるようになったことが開発者を刺激した。
    • 白石: 技術者が持っている期待感。他のプラットフォームは実装→仕様。HTML5は仕様から先に決まることが多い。
これからどうなる。3年先。
  • 白石
    • よりWeb/html5/jsが使われるようになる。
  • 小松
    • クラウド、デバイスのシームレスな連携がより進む。デバイスの話が出た途端にステークホルダーが増える(プレイヤーが増える)。TV, カーナビ, etc… 今では想像もつかないことが始まってるはず。
  • 羽田野
    • あらゆる表示画面がWebでできているかも。そのため機能面ではなく安定性などの非機能が重要になるのでは。
  • 及川
    • どんどんWebの範囲は広がっていく。認証して必要なものが増える。
    • クラウドではなくランデブーでつながないと遅くてやってられないものが増える(テレビとリモコンなど)。アーキテクチャは非常に複雑になる。
    • ステークホルダーが増えることによるスピード感をなくしてしまわないようにしなければならない。
感想
  • 3年後の話、HTML5は生活のいろんな所に実用的な形で入ってくると考えると、いろいろ取り巻く問題の種類が変わってくるということについて、今から準備しとかないとまずそうだと思った。
  • きっとHTML5関連技術を扱う人にもフロントだけでなくデバイス・インフラの技術が必要。

HTML5によるタフなモバイル開発の最前線(紀平さん)

  • 資料: 探し中
  • 今回の話の対象は、モバイルブラウザで「今」できること
モバイルHTML5の基礎
  • リッチといえばFlashだった(ガラケー時は非常に普及していた)
  • スマフォではFlash使えない
  • そこでHTML5が注目された
モバイルHTML5うれしいこと
  • ブラウザ間の互換性を保って使える機能が増えた
  • 曲線のある図形の描画ができるようになった、アニメ能力の向上
  • Webアプリ機能の向上
    • Application Cache, localStorageなど

しかし、ネイティブにはかなわない

  • 3D: iOS6ならもしかして。
  • 音楽: androidはOKだが、iOSがプア。クリックしないと再生しないとか。Winも貧弱。
  • 速度: 描画速度が特に。
    • Canvas, CSS3。モバイルHTML5の最前線は如何にCanvas/CSS3で描画速度を上げるかが最も熱い

Canvas VS CSS3

  • Canvas: 低レベル部分で言えばFlashでできることは代替できる
    • メリット
      • 最近のOSはGPUを使うので高速
      • APIがシンプルなので端末間の挙動の違いが小さい
    • デメリット
      • ただでさえろくでもない言語であるJSを書きまくるハメになる
  • ngCoreはCanvasベース。ネイティブに見える。
  • CSS3
    • メリット
      • 記述が簡潔
      • 基本的にGPUを使うので高速
      • CSSなのでデザイナーも書ける(JSerじゃなくても書ける)
    • デメリット
      • 細かいアニメの同期がとれない(JSでやらないといけない。ゲームには向かない)
      • ハマると異常に遅くなる。DOMが増えると遅くなりやすい。
      • 【端末間の互換性が絶望的】
        • Galaxy S3でビルドNoが同じなのに挙動が違うことも…
解決策
  • iOS: 端末間の差が少ないのでCSS3を使う
    • iOS4/5, 3GS/4/4Sだけ
    • そもそも互換性が高い
  • Android
    • これまではFlashだった
    • 今後は…課題
DeNACanvas
Canvasのノウハウ
  • DeNAのWebゲームではCavasをフルに使ったページが起動しっぱなし
  • 普通に使う場合に比べて、速度、メモリ、電池で課題が発生しやすい
  • 高速化
    • オンメモリCanvasの有効活用
    • GPUのサポートにより、drawImageが高速になった。
    • DOMに属さないCanvas要素をcreateElementで作成して、キャッシュすると高速化できる
    • GC対策
      • Androidは世代別GCを利用のでstop the worldが起こる(0.1秒ぐらいだがアクションゲームでは致命的)
      • 長期保存するメモリと短期メモリ を区別する
      • 最初に可能な限りオブジェクトをプールしてメモリ確保自体を減らす
  • メモリの問題
    • スマフォではメモリを使い過ぎると落ちる
    • 実機の使用量は動的に調査
      • iOS6からできるかも。Androidデバッグブリッジでやれる。
      • WebViewで表示して調べることも一般的。ただMobile SafariとWebViewではJITの有無が違うので正しい判断が難しい(JITはメモリを食うので)。Jail Breakしたらもしかしたら…
    • メモリリークを検知。Chrome Developer Tool: snapshot
      • domのイベントの解除忘れ
      • console.log(デバッグ中だけメモリリークが発生する…)
      • グローバルオブジェクトのヒモ付
  • 電池の問題
    • CPU使用率と相関
    • 描画のCPU使用率は高い
    • 描画しなくていい場合はとにかく描画しない
    • 前のフレームで描いた描画結果を利用して描画範囲を絞る(dirty rect)
今後のモバイルHTML5
  • ネイティブ VS HTML5
    • 一長一短
    • インストールなく実行できる(twitterのリンクからすぐ実行できる)
    • データの保存・速度は勝てない
  • html5らしいwebアプリはごく少数
    • iOS: gmail, twitter, Facebook
    • 優れたwebアプリの登場によって滋養今日は簡単にひっくり返る
  • きっと…
    • iphone/androidでちゃんと動く
    • ページ遷移なし
    • 瞬時に起動・オフラインで快適に使用
感想
  • 講演のように現状、HTML5のアニメーションの基盤技術は非常に貧弱。
  • 紀平さんような専門の技術者(チーム)による整備が必要だと思った。
    • 持っているノウハウがすごい。

ブラウザを介した新しいリアルタイムコミュニケーション(あんどうやすしさん)

  • テーマ: WebRTC
  • 資料: 探し中
Webのリアルタイムコミュニケーション

1. Ajax/Comet

  • Cometは技術の組み合わせ - WebRTCは標準技術

2. Server Side Event

  • サーバからのpush用 - WebRTCは双方向

3. WebSocket

  • サーバのプロセスとWebアプリの双方向通信
  • WebRTCはWebアプリ同士の双方向

- RTC (Real Time Communication)

    • 現状は音声/ビデオコミュニケーションができるだけ(P2Pとかはまだ)
  • ブラウザからカメラの情報を受け取って表示したりストリームをリモートピアに送信・受信できる
  • おいおいは「任意のデータ」をP2Pで通信できる
  • getUserMedia でカメラの映像を取り込んでいじれる
  • media stream -> ネットワーク or 画面
感想
  • 個人的に今後一番楽しみなところ。ブラウザで任意のP2P通信とか、いろんなデバイスとブラウザがつながるようになったらとても楽しそう。

HTML&CSS標準デザイン講座 【HTML5&CSS3対応】

HTML&CSS標準デザイン講座 【HTML5&CSS3対応】


node.jsでテキストファイルを読み込んでMySQLにデータを突っ込む

はじめに

MySQLで吐き出したテキストデータを別のMySQLに突っ込む必要があったので作成。
node.jsで何も考えずにI/O関連のコード書くと酷いことになるといういい例w

  • insert.js
var lazy = require('lazy');
var fs = require('fs');
var opts = require('opts');
var mysql = require('mysql');
var _ = require('underscore');
var async = require('async');

//全体で使う変数
var t = {
    def: {}, //テーブル定義
    name: ''
};

//コマンドライン引数の設定
opts.parse([
    {
		short: 't',
		long: 'table',
		description: 'table name',
		value: true,
		require: true
    },{
		short: 'f',
		long: 'file',
		description: 'data file',
		value: true,
		require: true
    },{
		short: 'd',
		long: 'def',
		description: 'table definision (json)',
		value: true,
		require: true
    }
]);

//コマンドライン引数の取得
t.name = opts.get('table');
var dataFile = opts.get('file');
var tDef = opts.get('def');
var tableInfo = null;

console.log('talbe: ' + t.name + ', data: ' + dataFile + ', table def: ' + tDef);

//MySQLの準備
var client = mysql.createClient({
    user: 'user_name',
    password: 'password'
});
client.query('use sample_db');

//前処理 テーブル作成など
var prep = function(table, importDataFunc){
    fs.readFile('./' + tDef, function(err, data){
	if(err){
	    console.log(err);
	}
	tableInfo = JSON.parse(data.toString('utf8'));
	var tableDef = tableInfo.def;

	var defs = [];
	_.each(tableDef, function(type, name){
	    defs.push(name + ' ' + type);
	});
	t.def = tableDef;

	var query = 'CREATE TABLE ' + table + '(' + defs.join(', ') + ');';	
	console.log(query);

	var createTable = function(datafile){
	    //テーブル作成
	    client.query(query, function(){
			console.log('table: ' + table + ' created!');
			importDataFunc(dataFile, createIndexes);
	    });
	};

	//テーブルが既に存在していたら削除する
	try{
	    client.query('DROP TABLE ' + table, function(err){
	    	createTable(dataFile);
	    });
	}catch(e){
	    console.log('already, ' + table +' is exist.');
	    createTable(dataFile);
	}
    });
};

//インデックス作成
var createIndexes = function(tableName, indexes){
    var queries = [];
    _.each(indexes, function(val, key){
    	var query = 'ALTER TABLE ' + tableName + ' ADD INDEX(' + val + ')';
		console.log(query);
		queries.push(query);
    });
    async.forEach(queries, function(query, cb){
		client.query(query, function(){
		    cb();
		});
    }, function(err){
		if(err){
		    console.log(err);
		}else{
		    console.log('create indexes');
		    client.query('COMMIT', function(){
			    process.exit();
		    });
		}
    });
};

//ファイルを読み込んでパースしてDBに書き込む
var queries = [];
var importData = function(table, createIndexesFunc){
    console.log('start import');
    var cols = [];
    _.each(t.def, function(type, name){
    	cols.push(name);
    });
    
    var queryBase = 'INSERT INTO ' + t.name + '(' + cols.join(', ') + ') VALUES (';

    var rs = fs.createReadStream(dataFile, {bufferSize: 256 * 1024});
    //forEachは非同期。rsのendイベントで完了を検知する
    rs.on('end', function(){
		//最初の一行はカラム定義とするので除去
		queries.shift();
	
		console.log('create ' + queries.length + ' queries');

		async.forEach(queries, function(query, cb){
		    client.query(query, function(){
				cb();
		    });
		}, function(err){
		    if(err){
		    	console.log(err);
		    } else {
				console.log('fin: ' + queries.length + ' queries.');
				createIndexesFunc(t.name, tableInfo.indexes);
		    }
		});
    });

    //ファイル読み込み開始
    new lazy(rs).lines.forEach(function(line){
		var items = line.toString().split('\t');
		_.each(items, function(val, i){
		    if(!val.match(/^[0-9]+/ && val !== 'NULL')){
			items[i] = '"' + val + '"';
		    }
		});
		var query = queryBase + items.join(', ') + ')';
		queries.push(query);
    });
};


client.query('SET autocommit=0', function(){
	client.query("START TRANSACTION", function(){
		prep(t.name, importData);
	});
});

以下みたいな感じでテーブル定義を指定する。

{
	"def": {
	       "user_id": "int unsigned",
	       "age": "int unsigned",
	       "name": "varchar(255)"
	},
	"indexes": [
	       "user_id"
	]
}

対象としているデータの形式は以下。

  • data.txt
user_id	age	name
10001	26	Taro
10002	18	二郎

実行方法

node insert.js -t 【テーブル名】 -d def.json -f data.txt

実践Node.js プログラミング (Programmer's SELECTION)

実践Node.js プログラミング (Programmer's SELECTION)

サーバサイドJavaScript Node.js入門 (アスキー書籍)

サーバサイドJavaScript Node.js入門 (アスキー書籍)