2024/09/01

NetLogo導入直後にはまった話(logging関連)

ゆえあってNetLogoを使う必要があったのでNetLogo6.4.0をインストールした。 自分が初めて触った言語がLOGOだったのでちょっと感慨深い。(どうでもいいけど、LOGOの子孫だけど"Logo"部分は小文字なのね) 

インストールして早速言語設定変更のために環境設定というところで、 「Enable logging」 という項目を発見。
自動でログ取ってくれるのかと思い早速チェックを入れて再起動。 

 …ここからが長い闘いの始まりだった。

起動しようとするとエラーが出て動かない。 

 Exception: netlogo_log_2024-06-01_20-12-55.614.json (アクセスが拒否されました。) (class java.io.FileNotFoundException)

そしてそのまま起動しない。スタックトレースも表示されているが、ファイルを開こうとして失敗したということしか書かれていない。
言語の変更は問題ないとしてどうやらloggingの設定のせいだろう。
問題は、起動できないので設定を変更できないということである。これは困る。

おそらく設定ファイル的なものがあってそれを読み込んでいるだろうと推測し、探すことにする。
まず探したのはNetLogoのインストールされたフォルダ(NetLogo 6.4.0)。フォルダ直下に設定ファイルらしきものはない。
NetLogo 6.4.0\runtime直下に"logging.properties"なるファイルがあるもののもこれも違うようだ。
仕方なくインターネットの知恵を借りて探すがヒットしない。


WindowsでNetLogoを起動しようとすると "The JVM could not be started" というエラーになります。助けて!
https://www.u.tsukuba.ac.jp/~kurahashi.setsuya.gf/NetLogo-ja/faq.html#windowsmemory

ほとんど確かな解決方法は、テキストエディターを使ってNetLogo 5.0.4.vmoptionsファイル(デフォルトではC:\Program FilesのNetLogoディレクトリにあります)を編集することです。

それがないんですよね。vmoptionsファイル。どうやらバージョンアップでなくなってしまったよう。
1日くらいかけて試行錯誤して

再インストール→×
修復インストール→×
confの修正→×

最終的な正解は、コマンドラインで実行して、管理者権限不要でアクセスできるフォルダを`--log-directory`で指定するでした。

NetLogoは割と使いやすい言語なのだが、使用者人口が多くないのでこういう落とし穴にはまったときの解決策がなかなか見つからない。










2021/05/13

読書関係つぶやき(2021.04-)

Resnick(1994)『非集中システム』


非集中システム

Camazine et al.(2001)『生物にとって自己組織化とは何か』


生物にとって自己組織化とは何か

Gancarz(1996)『Unixという考え方』


Unixという考え方

Johnson(2002)『創発―蟻・脳・都市・ソフトウェアの自己組織化ネットワーク』


創発―蟻・脳・都市・ソフトウェアの自己組織化ネットワーク

2020/05/21

「ノート:心理学史」を公開しました


はるか昔に公務員試験(心理職)対策用に作ったノートが発掘されたので資料として公開します。





学生時代はあまり心理学史を学ぶ機会がなかったので、これはいい機会ということで3~4冊くらい教科書を読みながらまとめたものです。

今はどうかわからないですが、心理職は精神分析が出やすいらしい、ということでそこもちょっとだけ重点的に記述があります(精神力動なんもわからん状態だったので)

社会心理学はもちろん、臨床心理学とか進化心理学とかの潮流はカバーできていないので機会があればアップデートしたいなと考えています。



Webページ版
https://satocos135.github.io/history_of_psychology/



GitHubのページ
https://github.com/satocos135/history_of_psychology


2019/02/03

AnacondaのNumpyはpipではアップデートできない

みたいで、ハマった。
どうもcondaでアップデートしないとダメなようだ。
  $ conda install numpy
調べたところ、condaで入れたものとpipで入れたものが競合する場合があるとのこと↓
condaとpip:混ぜるな危険 - onoz000’s blog | http://onoz000.hatenablog.com/entry/2018/02/11/142347
実際、自分の環境で
  $ conda update --all
をかけるとエラーが出てアップデートできない。見事にcondaとpipが競合している。
まあ個別にアップデートするのは可能そうなので、当面は放置。

2018/06/30

高速データ処理ツールnysolのMCMD(Mコマンド)を試してみる


というわけで早速使ってみる。
Windows上での環境構築については前回の記事を参照のこと。

環境


Windows 10(64bit)
CPU: Intel Core i7-7500U
メモリ: 16GB
Bash on Windows(Ubuntu 16.04.4 LTS (Xenial Xerus))

データ


MovieLens ml-20M(Harper and Konstan,2015*)を使う。
映画の評価情報が入っているデータセットである。
同梱のREADMEには

This dataset (ml-20m) describes 5-star rating and free-text tagging activity from [MovieLens](http://movielens.org), a movie recommendation service. It contains 20000263 ratings and 465564 tag applications across 27278 movies. These data were created by 138493 users between January 09, 1995 and March 31, 2015. This dataset was generated on March 31, 2015, and updated on October 17, 2016 to update links.csv and add genome-* files.
(邦訳筆者:)このデータセット(ml-20m)は映画推薦サービスMovieLens上の5段階評価のレイティングおよび自由記述によるタグ付け情報からなる。2,0000,263件の評価、27,278件の映画とそれらにタグ付けされた465,564のタグ情報を含む。データは1995/01/09~2015/03/31の期間、138,493人のユーザーのものを収集した。データセットは2015/03/31に出力され、2016/10/17にアップデートがなされた(links.csvおよびgenome-で始まるファイル群が付加された)

とある。

比較的大きめのデータセットで、解凍すると全体で約800MBにもなる。
nysolを試すのにはちょうどよいだろう。

ファイル構成はこんな感じ。

$ ls
genome-scores.csv  genome-tags.csv  links.csv  movies.csv  ratings.csv  README.txt  tags.csv

今回はこのうちmovie.csv(約1.3MB)およびratings.csv(約500MB)を使ってみる。
ちょっと中身を見てみると、moviesは各映画のIDとタイトル、ジャンルといった基本情報、

$ head movies.csv
movieId,title,genres
1,Toy Story (1995),Adventure|Animation|Children|Comedy|Fantasy
2,Jumanji (1995),Adventure|Children|Fantasy
3,Grumpier Old Men (1995),Comedy|Romance
4,Waiting to Exhale (1995),Comedy|Drama|Romance
5,Father of the Bride Part II (1995),Comedy
6,Heat (1995),Action|Crime|Thriller
7,Sabrina (1995),Comedy|Romance
8,Tom and Huck (1995),Adventure|Children
9,Sudden Death (1995),Action

ratingsは評価したユーザのIDと映画のID、評点、および評価した時刻(unix秒)、

$ head ratings.csv
userId,movieId,rating,timestamp
1,2,3.5,1112486027
1,29,3.5,1112484676
1,32,3.5,1112484819
1,47,3.5,1112484727
1,50,3.5,1112484580
1,112,3.5,1094785740
1,151,4.0,1094785734
1,223,4.0,1112485573
1,253,4.0,1112484940

がそれぞれ入っている。


処理


nysolは複数のコマンド群からなる。
このうち基本的な処理をつかさどるのがMCMD(Mコマンド)パッケージである。
Mコマンドというだけあって、すべてのコマンドの頭にmの字がついている(ちなみにMは考案者の苗字にちなんでいるそうだ。)

各コマンドはパラメータiで入力ファイル名、パラメータoで出力ファイル名を指定する。
特に入出力ファイルの指定がなければ標準入出力を使う。

そのためパイプ処理的に次々とつなげて使うことができる。

$ {コマンド1} i={入力ファイル名} | {コマンド2} | ... | {コマンドn} o={出力ファイル名}

もちろん、パイプ処理で普通のunixコマンドに渡すこともできる。
パイプを活用し、並行処理をすることによって、CPUやメモリを効率的に扱える…らしい。
今回はml-20Mデータセットを使いつつ、MCMDを簡単に使ってみる。

mcut: 列を選択する

mcutは行から選択した列を抜き出すコマンド。

$ mcut f={項目名1},{項目名2}
※コンマの後には空白を入れない。

パラメータfで必要な列を選択する(fは何の略だろう…focus?)。
パイプラインに逐次データを流しこむ都合上、早い段階で必要な項目だけに絞り込んで流すデータ量を減らしたい。

movies内のIDおよびタイトルのみを切り出し、headコマンドに渡して先頭10行だけ出力してみる。

$ time mcut f=movieId,title i=movies.csv | head
movieId,title
1,Toy Story (1995)
2,Jumanji (1995)
3,Grumpier Old Men (1995)
4,Waiting to Exhale (1995)
5,Father of the Bride Part II (1995)
6,Heat (1995)
7,Sabrina (1995)
8,Tom and Huck (1995)
9,Sudden Death (1995)
#END# kgcut f=movieId,title i=movies.csv; IN=27278 OUT=27278; 2018/06/30 12:48:14

real    0m0.130s
user    0m0.000s
sys     0m0.047s
※行頭のtimeは時間計測用のコマンド

1MB程度のファイルだと一瞬で処理が終わるのがわかる。

mcount: 行を数える

mcountは行を数えるコマンド。
$ mcount  a={新しい列名} [k=数える対象の列]

パラメータaで集約した列の名前、パラメータkで数える対象の列を指定する(kはkeyとして、aはas?)。
kを指定しない場合は全部の行を数える。
なお、kで指定していない列の値は不定(適当なデータが選ばれる)なので当てにしない。

ユーザーが映画を評価したデータ(ratings.csv)を用いて、各映画の評価がどれだけ投稿されているかの回数を調べたい。そういうときにmcountが役に立つ。

$ time mcount a=count k=movieId i=ratings.csv | head
,count,movieId%0,rating,timestamp
,496951,4.5,1379744413
,2900510,4.0,843239650
,4115,100,3.0,942233644
,203,1000,4.0,868380324
,348,100003,2.0,1402337250
,1026,100006,2.5,1358891058
,6398,100008,4.0,1358823364
,2217,100010,3.0,1395061487
,50827,100013,2.5,1381595359
#END# kgcount a=count i=ratings.csv k=movieId; IN=20000263 OUT=26744; 2018/06/30 13:25:28

real    0m21.086s
user    0m19.391s
sys     0m4.297s

なんだか表示がおかしい…と思ったら、改行コードが悪さをしていた。
nysolで扱うcsvの改行コードはunix式(LF)のみとのこと。
このデータセットの改行コードはdos式(CRLF)なので、出力時に不具合が生じていたらしい。

そこでnkfなどのツールを用いて改行コードを変えてやる必要がある。
前回構築した環境ではnkfはデフォルトでは入っていなかったのでとりあえずインストールしてやる。

$ sudo apt-get install nkf
$ nkf -Lu ratings.csv > _ratings.csv
$ nkf -Lu movies.csv > _movies.csv

この新しいファイルでやってみると

$ time mcount a=count k=movieId i=_ratings.csv | head
userId,movieId%0,rating,timestamp,count
65891,1,4.0,965331158,49695
31323,10,4.0,1121207588,29005
91696,100,4.0,833287336,4115
21055,1000,4.0,940160814,203
19153,100003,5.0,1364238516,3
73026,100006,2.5,1358891058,1
21398,100008,4.0,1358823364,6
53478,100010,4.0,1394292232,22
134567,100013,3.5,1418289706,5
#END# kgcount a=count i=_ratings.csv k=movieId; IN=20000263 OUT=26744; 2018/06/30 13:27:06

real    0m27.944s
user    0m24.281s
sys     0m5.203s

綺麗に出力された。

さてここでID(movieId)および評価回数(count)以外の列の値は不定なため意味のある値でない。そこでmcutと組み合わせてやれば、

$ time mcut f=movieId i=_ratings.csv | mcount a=count k=movieId | head
#END# kgcut f=movieId i=_ratings.csv; IN=20000263 OUT=20000263; 2018/06/30 16:09:02
movieId%0,count
1,49695
10,29005
100,4115
1000,203
100003,3
100006,1
100008,6
100010,22
100013,5
#END# kgcount a=count k=movieId; IN=20000263 OUT=26744; 2018/06/30 16:09:15

real    0m22.724s
user    0m21.688s
sys     0m4.109s

となり不要な列を削除して表示できる。

mbest: ソートして指定の行数を返す

せっかく集計したので評価回数の多い映画のリストを出力したい。
そこでmbestコマンドを使って上位のレコードを取得する。

$ mbest s={ソートする列名}[並べ替えオプション] size={取得する行数}

パラメータsでソートする列名を指定する(sはsortだろうか)、
並べ替えは、デフォルトでは文字列・昇順で行われるが、
項目名の後にオプションをつけることで方式を指定できる。

%r ...文字列・降順
%n ...数値・昇順
%nr ...数値・降順

(n がnumericとして、r はreversed?)
ここでは評価回数について降順(大きい方から順に)でデータを取得したいので、並べ替えオプションには%nrと指定してやる

$ time mcut f=movieId i=_ratings.csv | mcount a=count k=movieId | mbest s=count%nr size=10
#END# kgcut f=movieId i=_ratings.csv; IN=20000263 OUT=20000263; 2018/06/30 16:13:13
#END# kgcount a=count k=movieId; IN=20000263 OUT=26744; 2018/06/30 16:13:25
movieId,count%0nr
296,67310
356,66172
318,63366
593,63299
480,59715
260,54502
110,53769
589,52244
2571,51334
527,50054
#END# kgbest s=count%nr size=10; IN=11 OUT=10; 2018/06/30 16:13:25

real    0m22.447s
user    0m19.797s
sys     0m3.594s
(mbestで出力するサイズを指定できるためheadに渡す必要がなくなった。)

mjoin: データを結合する

さて、上位の件数が求まったところで、映画のIDだけではこの映画が何かを知ることはできない。そこでmjoinを使い、映画のIDとタイトルが紐付いたファイル(movies.csv)からタイトルのデータを引っ張ってくることにする。
mjoinコマンドはデータを結合するコマンド。

$ (何らかの処理) | mjoin k={統合に使うキー} i={読み込むファイル名}

受け取ったデータをキーをもとに統合する。これを使えば、

$ time mcut f=movieId i=_ratings.csv |mcount a=count k=movieId |mbest s=count%nr size=10|mjoin k=movieId i=_movies.csv
#END# kgcut f=movieId i=_ratings.csv; IN=20000263 OUT=20000263; 2018/06/30 16:23:32
#END# kgcount a=count k=movieId; IN=20000263 OUT=26744; 2018/06/30 16:23:43
#END# kgbest s=count%nr size=10; IN=11 OUT=10; 2018/06/30 16:23:43
movieId%0,title,genres,count
110,Braveheart (1995),Action|Drama|War,53769
2571,"Matrix, The (1999)",Action|Sci-Fi|Thriller,51334
260,Star Wars: Episode IV - A New Hope (1977),Action|Adventure|Sci-Fi,54502
296,Pulp Fiction (1994),Comedy|Crime|Drama|Thriller,67310
318,"Shawshank Redemption, The (1994)",Crime|Drama,63366
356,Forrest Gump (1994),Comedy|Drama|Romance|War,66172
480,Jurassic Park (1993),Action|Adventure|Sci-Fi|Thriller,59715
527,Schindler's List (1993),Drama|War,50054
589,Terminator 2: Judgment Day (1991),Action|Sci-Fi,52244
593,"Silence of the Lambs, The (1991)",Crime|Horror|Thriller,63299
#END# kgjoin i=_movies.csv k=movieId; IN=27278 OUT=10; 2018/06/30 16:23:43

real    0m20.631s
user    0m17.438s
sys     0m3.391s

タイトルを引っ張ってくることができる。
こいつを多少整形してやると、

$ time mcut f=movieId i=_ratings.csv |mcount a=count k=movieId |mbest s=count%nr size=10|mjoin k=movieId i=_movies.csv | mcut f=count,title | msortf f=count%nr
#END# kgcut f=movieId i=_ratings.csv; IN=20000263 OUT=20000263; 2018/06/30 16:34:39
#END# kgcount a=count k=movieId; IN=20000263 OUT=26744; 2018/06/30 16:34:50
#END# kgbest s=count%nr size=10; IN=11 OUT=10; 2018/06/30 16:34:50
#END# kgjoin i=_movies.csv k=movieId; IN=27278 OUT=10; 2018/06/30 16:34:51
#END# kgcut f=count,title; IN=10 OUT=10; 2018/06/30 16:34:51
count%0nr,title
67310,Pulp Fiction (1994)
66172,Forrest Gump (1994)
63366,"Shawshank Redemption, The (1994)"
63299,"Silence of the Lambs, The (1991)"
59715,Jurassic Park (1993)
54502,Star Wars: Episode IV - A New Hope (1977)
53769,Braveheart (1995)
52244,Terminator 2: Judgment Day (1991)
51334,"Matrix, The (1999)"
50054,Schindler's List (1993)
#END# kgsortf f=count%nr; IN=10 OUT=10; 2018/06/30 16:34:51

real    0m21.086s
user    0m17.641s
sys     0m3.766s

これでサイト上で評価回数の多かった映画10件の評価数、ならびにそのタイトルが出力できた。
こんな感じで比較的高速にデータを処理できる。

後記

今回はデモだったので中間処理ファイルを保存せずにいちいちコマンドを書いていたが、
ある程度何度も使うような処理結果に関しては途中経過を適宜ファイルに保存しておくとよい。

また、コマンドの処理結果を試すのにいちいち全ファイルを読み込むのも煩雑なので、
色々試したいときは少量の行数を読み込んで作業するといいだろう。
例えばheadコマンドでデータ読み込んでパイプで渡してやるとサクサク動くのでよい。

$ head {ファイル名} | {mコマンド}



ハマった点は、改行コード以外ではmcountコマンド。mcountではソートされた結果に基づいて行をカウントしているので、コマンド実行時にqオプション(自動ソートにしない)をつけると正常にカウントされない。特に警告も出ないので、原因解明に時間がかかった。

今のところWeb上にそんなに情報もないので、利用者が増えて知見が蓄積されていくことを期待したいところ。

引用文献


* F. Maxwell Harper and Joseph A. Konstan. 2015. The MovieLens Datasets: History and Context. ACM Transactions on Interactive Intelligent Systems (TiiS) 5, 4, Article 19 (December 2015), 19 pages. DOI=<http://dx.doi.org/10.1145/2827872>


2018/06/29

高速データ処理ツールnysolをBash on Windows (Subsystem for Linux)で動かす

要約


データ処理ツールnysolをWindows PCで動かすまで。

環境 


Microsoft Windows 10(64bit)


経緯


コマンドライン上でcsv形式のデータを高速に処理できるnysolなるものがあるという。


NYSOL(にそる)はデータ分析のためのオープンソースソフトウェアで,2003 年にリリースされたMUSASHIの後継となる.NYSOL の特徴は,大規模なCSV データに対して単一の処理に特化したコマンド群を組み合わせることで,データの加工・前処理から,マイニングアルゴリズムの適用まで,KDD (Knowledge Discovery in Databases) の全プロセスを効率よく実現できる.そして1 億件以上の大規模データをPC で処理することが可能である.
中原・中本・羽室(2016)*

気になる。

しかし公式ドキュメントを読んだところ、残念ながらWindows上ではそのままでは動かない。
Windows上で動かす選択肢としては

1. Virtual box上で動かす
2. Cygwin上で動かす
3. Bash on Windows(Windows Subsystem for Linux)上で動かす

があるが、わざわざVirtual Boxを立ち上げて動かすのは面倒。

手軽に動かしたいので、既に入っているGit Bashで動かそうと挑戦したものの、
そちらは諸々のライブラリの入れ方がわからず失敗。

そこでBash on Windows(Windows Subsystem for Linux)を導入し、インストールすることにした。
これを使えば、コマンドプロンプトからUbuntu上のbashに簡単に遷移できる。

手順


Bash on Windowsの導入は以下のリンクを参考にした。

Windows Subsystem for Linuxをインストールしてみよう!

これでUbuntuが入るところまではできるので、今度は公式ページを参考にする

インストール - NYSOL

今回入れたのはUbuntuなので「Ubuntu Linux」の項を見ればよい。
公式ページ経由で最新版(今回は2.4)のインストール用のファイルをダウンロードする。

nysol_2.4-0_amd64.deb

をダウンロード。

これをそのままインストールしようとしたらgemがないと言われて怒られるので、rbenvを入れる(こだわりがなければ普通のrubyでもいいかもしれない)。

$ sudo apt-get install rbenv

rbenvが入った段階でnysolがインストール可能になる。

$ sudo dpkg -i nysol_2.4-0_amd64.deb

インストールが完了したらnysolのコマンドが動くかどうか確認する。
$ mcut -version
lib Version 2:1:0:0: mod Vesion 2773f52145b34ff52ac0ec5a7181496380fa3dca

これでnysolが使える状況にはなったようだ。
とりあえず今日はここまで。

次回はこれを使ってデータの加工に取り組みたい。

引用文献


* 中原 孝信・中元 政一・羽室 行信(2016). ビッグデータ解析ツールNYSOL
―性能評価,並列処理,ビジネス応用ケース―. オペレーションズ・リサーチ 61(1), 11-18.

2018/06/25

分析のガイドライン


院生だった頃に学部生の指導用に作った資料をSlideShareにて公開しました。
データ収集&クリーニングが終わってさあ分析だ、となった際にそこからどういう流れで展開するのかについて軽くまとめたものです。

多少背景を説明すると、私がTAをしていた実習(自分たちで仮説を立ててデータ収集・分析からレポート作成までやるという内容)の補助資料としてこういうものを作りました。

レベルとしては、座学で一応入門レベルの統計学の知識を学んだものの実データでの分析はやったことがない、という程度を想定しています。

実データを解析するにあたって意外と取りこぼされそうなところ(再現性&効率性の重要さ)を強調して書きましたが、多少煩雑かもしれません。一方で、統計分析の細かいところについては割愛しています。

こういった資料を眠らせたままにしておくのももったいないので、今後折をみて世に出していきたいです。



2018/03/11

複数のcsv/tsvをまとめてひとつのExcelファイルにしたい[python]


複数の分析結果をcsvで出力したりしたものをひとつにまとめたくなったのでメモ。


import pandas as pd
import os
import re
import openpyxl as opx

# tsvの入っているフォルダの名前
folder_name = 'folder'

# フォルダのリストを列挙
files =  os.listdir(folder_name)
# 拡張子がtsvのものだけを抜き出す + ファイルのパスを付加
files = [folder_name + x for x in files if re.search(r'\.tsv$', x)]

# 出力ファイル名
filename = 'output.xlsx'

# エクセルのシートに各ファイルを格納
EXL =pd.ExcelWriter(filename, engine='openpyxl')
for filepath in files:
    sheet = pd.read_csv(filepath, sep='\t')
    sheet.to_excel(EXL, sheet_name=filepath.replace(folder_name, ''), index=False)

# 保存
EXL.save()

2018/02/26

An Illustrated Guide to Theoretical Biology ch01レジュメ

勉強会で発表した資料。

テキストは
Case(1999) An Illustrated Guide to Theoretical Biology

発表した第一章”Exponential and Geometric Population Growth”は
個体群動態を考える基礎となる集団の指数的成長・幾何級数的成長を扱っている。

pdf

2017/05/05

Bitcoin: A Peer-to-Peer Electronic Cash Systemレジュメ


勉強会でビットコインの元論文(Nakamoto, 2008)を読んだときのレジュメを公開してみる。

自分も含め誰も詳しく知らない分野のため、レジュメは要約することよりもむしろ議論のディテールが把握できるような構成をこころがけた。
ところどころ用語や言い回しが変だったり、表現が不正確だったりするところがあると思うのでご指摘いただければ。

なお元の論文についてはhttps://bitcoin.org/ から入手可能。

Nakamoto, S. (2008): Bitcoin: A Peer-to-Peer Electronic Cash System


ビットコイン:P2Pを用いた電子通貨システム

Abstract A purely peer-to-peer version of electronic cash would allow online payments to be sent directly from one party to another without going through a financial institution. Digital signatures provide part of the solution, but the main benefits are lost if a trusted third party is still required to prevent double-spending. We propose a solution to the double-spending problem using a peer-to-peer network. The network timestamps transactions by hashing them into an ongoing chain of hash-based proof-of-work, forming a record that cannot be changed without redoing the proof-of-work. The longest chain not only serves as proof of the sequence of events witnessed, but proof that it came from the largest pool of CPU power. As long as a majority of CPU power is controlled by nodes that are not cooperating to attack the network, they'll generate the longest chain and outpace attackers. The network itself requires minimal structure. Messages are broadcast on a best effort basis, and nodes can leave and rejoin the network at will, accepting the longest proof-of-work chain as proof of what happened while they were gone.

要旨:純粋にPeer-to-Peer方式である電子通貨は金融機関を仲介することなく二者間の直接のオンライン決済を可能にする。この方式には電子署名が重要な役割を果たしているが、二重支払を防ぐために信頼できる第三者のような存在を必要とするのであれば、[仲介者を必要としないという]主要な利点が失われてしまう。[そこで]我々はPeer-to-Peerネットワークを用いて二重支払問題を解決する方式を提案する。ネットワークは取引をハッシュ化し、現在進行形で伸長するハッシュベースのProof of Workのチェーンに記録することで、取引とその時刻を記録する。これはProof of Workを再実行しなければ変更することのできない記録となる。最長のチェーンは一連の取引の証拠として機能するだけでなく、それが[数あるチェーンの中で]最大のCPU パワーの集積によって作られたものであるということを担保する。CPUパワーの過半数が攻撃者のコントロール下にない限り、ネットワークは最長のチェーンを更新し続け、攻撃者[の計算能力]を凌駕し続ける。ネットワーク自体は最小限の構造しか要求しない。[ノード間の]メッセージはベストエフォートベースで広められる。最長のProof of Workのチェーンの記録を採用するため、ノードは随意にネットワークを離脱したり再接続したりできる。

1. Introduction


イントロダクション
  • 旧来のインターネット取引:信頼(trust)ベースのモデル
    • 信頼できる第三者(trusted third party)が必要
  • 不可逆的な(=記録を改竄できない)取引には「信頼できる第三者」が必要。ただし:
    • 仲介の問題を避けて通れない
    • 仲介のための費用が増大 
      • 最小の取引量があるなどの制限がある
  • 暗号学的な証明システムが信頼ベースのシステムに替わって必要
    • 計算論的に改竄が困難であることを利用
本論文:二重取引の解決手段として、Peer-To-Peerの分散型タイムスタンプサーバを用いたシステムを提案する

2. Transaction

(発表者による補足)
基礎知識①:ハッシュ関数 
  • 値を入力すると一定長のデータを出力する関数。
  • 同じ値を入れればいつでも同じ値が出てくる
  • 一方向性を持つ
    • 入力$x$と出力$f(x)$について、$x$から$f(x)$を求めるのは容易であるが、$f(x)$から$x$を復元・推測することはできない
    • $x$がわからなければ、$f(x)$を生成できない
ハッシュ関数を用いた認証手順の例
    • クライアント:idとパスワード$a$を持つ
    • システム: 入力された値$a$からハッシュ値$f(a)$を計算
    • サーバ:idとハッシュ値$f(a)$の組をデータベースに保管
    • 手順:
        1. 認証時にクライアントはidとパスワード$a$をシステムに入力
        2. システムは$f(a)$を計算し、idと一緒にサーバに渡す
        3. サーバは登録されているidとハッシュ値の組を確認、正しければ認証
  • 利点  サーバが破られても$a$の値は洩れない(洩れるのは$f(a)$の値のみ)→パスワードそのものを保存していないので安全
    • これは印章(判子)と印影の関係に似ている 
      • クライアント:いつでも印影(ハッシュ)を発行できることで自分が印章(パスワード)の持ち主であるということを証明
      • サーバ:登録された印影が正しいかを比較することで、印章の正しさを確認。印章そのものを持っているわけではないので、印影を再発行することはできない。

基礎知識②:公開鍵暗号 
  • 安全に通信をするための暗号方式
    • 鍵をかける鍵と、 鍵を開ける鍵からなる 二つの鍵はセットになっている
    • 事前に鍵をかける鍵を公開しておく(公開鍵: Public Key)
    • メッセージの送り手は公開鍵を用いてメッセージを暗号化して受け手に送る
    • 受け手は自分だけが持っている鍵(秘密鍵: Private Key)でメッセージを復号化する
    • 暗号化されたメッセージは公開鍵では復号することができないので、メッセージが洩れても大丈夫
  • 認証の場合は手順が逆になる;
    • 事前に鍵を開ける鍵を公開しておく(公開鍵)
    • 送り手は自分だけが持っている鍵(秘密鍵)でメッセージを暗号化して受け手に送る
    • 受け手は公開鍵を用いてメッセージを復号化する
    • その公開鍵で復号できるのは送り手の持っている秘密鍵だけなので、送り手の真正性が立証される
(補足ここまで)

取引
  • 電子署名のチェーンとして電子的なコインを定義する
    • (チェーンの一番新しい位置にいる人物がコインを所有しているとみなす)
  • 所有者①から所有者②に所有権が移転した場合について考える
    • 前回の取引内容と所有者②の公開鍵でハッシュを生成する
    • これを所有者①の秘密鍵で暗号化し、署名とする
    • 所有者①の公開鍵を用いて、署名を検証できる
    • (所有者①が電子署名することによって所有権が移転したことを担保する)
  • 問題点:受取人は、コインが二重払いされていないこと(=それ以前に使用されていないこと)を検証できない
  • 受取人が、コインの前の保有者がそれ以前にコインを使用していないことを検証できる仕組みがいる
    • →所有権が移転してからの最初の取引だけ着目すればよい (一度使われたコインの二回目以降の取引はすべて無効とすればよい)
    • 旧来の解決手段:造幣局(Mint)の導入
      • すべての取引を監視、複数支払があった場合、最初に行われた取引だけを有効なものとして認める
      • ただし、中央集権的になってしまう
    • 信頼できる第三者が存在しない場合:取引をネットワークに公表(Publicly Announced)する
      • 取引の履歴ががただひとつに定まるようなシステムが必要


3. Timestamp Server

  • タイムスタンプサーバ
    • ハッシュを公開
      • ブロック(いくつかの取引の記録)をタイムスタンプとともにハッシュ化して知らせる
      • 時点$t+1$のハッシュ: 時点$t$のブロックとTimestampをハッシュ化したもの
    • あるデータがある時間に存在したことを証明
    • 各タイムスタンプはひとつ前のタイムスタンプをハッシュとして含むので、チェーン構造になっている

    4. Proof of Work


    Proof of Work(仕事の証明)
    クライアント側のコストを上げることによって攻撃を不利にする仕組み cf. HashCash
    リクエストの処理に一定(以上)の作業を要求する
    • BitcoinにおけるProof of Work:ブロックを追加(登録)するための作業
      • 一定以上の数のゼロの連続から始まるハッシュ値を探索する
      • ナンス(nonce)と呼ばれる数字を変更し、ブロック全体のハッシュ値が条件を満たすようにする
        • いわば$f(data+nonce)$=(条件をみたすハッシュ)となるnonceを求める作業
      • 平均的な計算量は指数的に増加(総当たり的な探索)
      • チェーンを再生成(改竄)するにはすべての計算を繰り返さないといけない
      • (注:Proof of Workを達成したブロックのみが次のブロックとして認められる。追加したブロックがチェーンに受け入れられれば報酬がある)
    • (正しいチェーンを決める)多数決の方法
      • Proof of Workを使うことで、どれを正しいチェーンとして認めるかという問題が解決する
      • 投票の方法
        • ×IPベース(IPひとつにつき一票)
          • 大量のIPを持っているものが有利
        • ○CPUベース(CPUパワーに応じた投票)
          • 最長のチェーンを選ぶようにすればよい(改竄するには過半数を超えるCPUパワーが必要になる)
      • 最長のチェーンを保持するには最大のProof of Workが必要
        • honest nodeが過半数ならば、honest chainがもっともよく伸びる
        • 過去のブロックを修正するためには(現在進行形で伸張する最長のチェーンを上回るスピードで)ブロックのProof of Workを繰り返し、続くチェーンをすべて改竄しないといけない
    ハードウェアの進歩やノードの拡大によって計算時間が変わってくるので、Proof of Workの困難さは適宜調整する必要がある。

    5. Network


    ネットワークの仕組み
    1. 新しい取引はすべてのノードに伝えられる
    2. それぞれのノードはブロックに新しい取引の情報を保管する
    3. それぞれのノードは、そのブロック内のProof of Workを見つけようとする
    4. ノードがProof of Workを見つけると、ブロックをすべてのノードに伝達する
    5. ノードは、ブロック内の取引が有効であり(そのブロックが)未使用である場合のみブロックを受け入れる
    6. ノードは受け取ったブロックを用いてチェーンに新しいブロックを作り出し、ブロックを受け入れたということを示す
    • ノードは常に最長のチェーンを正しいものとしてみなし、伸ばし続ける
      • タイになったら次のProof of Workが見つかるまで両方のブロックを保持して作業し、いずれか長くなった方のブロックに移動する
    • 新しい取引はすべてのノードに届かなくても大丈夫
      • 多くのノードに届けばいつか届く
    • メッセージの欠落にも寛容
      • ノードがブロックを受け取り損ねても、次のブロックを受け取ったときにないことに気付ける

    6. Incentive 


    インセンティブ
    • ブロックの最初の取引で、ブロックを作成した人に新しいコインが渡される
      • 参加者がネットワークを支持するインセンティブになる
    • 採掘:貨幣の発行と同じ効果→貨幣を発行する中央当局がいらない
    • ブロックに取引を追加するための手数料(transaction fee)を導入することによって、ブロックを採掘するインセンティブを保つことができる。(注:手数料を支払うと、より早く取引が処理される、という仕組みがある)
      • コインが採掘され終わると取引費用の方に主要なインセンティブは移るだろう
    インセンティブはノードに誠実であることを推奨する→不正を行うよりも採掘するほうに回った方が得であるということ

    7. Reclaiming Disk Space 


    ディスクの再利用
    新しいコインがブロックで埋まってくると、以前の取引を破棄してディスクスペースを開放する。取引はマークル木(Merkle Tree)の形で保管されており、ブロックのハッシュはマークル木のルート(根)ハッシュのみが含まれる→ブロックのハッシュを破壊せずに、古いブロックのデータを削減できる。

    (発表者による補足)
    $ T_{x0},T_{x1},T_{x2},T_{x3} $の4つの取引の記録がハッシュ値($Hash0, Hash1, Hash2, Hash3$)としてそのまま保存されていた場合、全体を検証するためにはすべての値を調べなければならず、非効率。 そこで、それぞれのハッシュをもとにハッシュを作るというハッシュ木(マークル木)を作成する

    $Hash01=f(Hash0+Hash1)$

    $Hash23=f(Hash2+Hash3)$

    $RootHash=f(Hash01+Hash23)$

    このRootHashの値が同じかどうかを調べれば、ブロックに含まれる取引の値が同じかどうかを効率的に調べることができる。

    ※出力が違うならば入力が異なっている $\iff$入力が同じならば出力が同じである(ハッシュ関数の性質)

    (補足ここまで)

    なおブロックは十分に小さいので、メモリに格納することになっても問題にならない

    8. Simplified Payment Verification


    簡略な支払いの検証
    • すべてのチェインのノードを走査せずに支払いを検証することが可能
    • 検証方法:ユーザーは最長のチェーンのブロックヘッダを持っていればよい
      • 最長のチェーンを検索し、取引に対応するタイムスタンプの入っているマークル枝を見つければよい
        • ネットワークがその取引を(正しい記録として)受け入れたということが確認できる
      • ネットワークが誠実なノードのコントロール下にあれば真正性を証明できる
      • ただし攻撃者が膨大な計算量を保持し続けている場合には脆弱性がある
        • 改竄が行われていないか検知する仕組みが必要になる

    9. Combining and Splitting Value


    価値の統合と分割
    • 複数の入出力があれば、価値を分割・統合することが可能

    10. Privacy


    プライバシー
    • 銀行におけるプライバシーの確保:銀行自体は個人情報を集めるが、他のユーザーに情報のアクセスを制限させることでプライバシーを守る
    • Bitcoin:公開鍵(認証鍵)を匿名にすることで、個人と取引の結びつきをわからなくする 
      • 取引がされていることはわかるが、それが誰と誰の間のものかはわからない

    11. Calculation


    (改竄することの困難性についての計算。割愛)

    12. Conclusion


    まとめ

    本論文:信頼によらない電子取引システムを提案

    従来の電子署名方式→所有権に関しては堅牢、二重支払に関しては脆弱

    提案した手法:
    • Peer to PeerネットワークとProof of workを用いて取引履歴を記録
    • CPUパワーの過半数が誠実なノードにある限り改竄は計算論的に実行困難
    • ネットワークはシンプルなのでロバスト 協調不要 個人の特定も不要
    • ノードの接続・離脱は随時可能
    代表となるチェーンを決定するために、ノードはCPUパワーを投票し、そのブロックをさらに拡張しようとすることでそのブロックを認めたことを表現する。 必要とされるルールやインセンティブはこの合意メカニズムを用いることによって強化されるだろう。

    (以上)


    2017/04/30

    Jupyter NotebookでRを動かす(windows)

    Jupyter Notebook上でRを動くようにしたときのメモ。

    1. 目的

    手持ちのWindowsのノートにPython環境をセットアップする。
    ついでにRもJupyter Notebook上で動くようにする。

    2. 環境

    OS: Windows 7 Professional(64bit)
    CPU: Core i5-4300U 1.9GHz
    メモリ: 4.00GB

    R 3.4.0
    Anaconda 4.3.1 (Python 3.6 version)

    3. 手順

    3.1 おおまかな流れ:

    下準備
    • Anacondaを入れる
    • Rを入れる
    Jupyter NotebookでRを使うための設定
    • IR Kernelを入れる

    3.2 Anacondaをインストールする

    Download Anaconda Now! | Continuum
    https://www.continuum.io/downloads

    Anacondaを使えばPythonでの分析環境が簡単に構築できる。
    自分がひいこら言いながらPythonをインストールしようとしてしかも失敗して断念していた頃とは隔世の感がある。

    細かいことに関してはこちらの記事を参照するのがよい:

    データサイエンティストを目指す人のpython環境構築 2016 - Qiita
    http://qiita.com/y__sama/items/5b62d31cb7e6ed50f02c

    今回はAnaconda 4.3.1 (Python 3.6 version) 64-bit installerを使ってインストールした。
    インストールが完了すると既にJupyter Notebookが使える状態になっている。
    プログラム一覧の中にあるJupyter Notebookを実行すればサーバーが立ち上がり、ブラウザ上でJupyter Notebookが使える。

    3.3 Rをインストールする

    R: The R Project for Statistical Computing
    https://www.r-project.org/

    公式サイトからRのインストーラをダウンロードしてきてインストールする。
    もちろん既にRがインストールされている場合はこの限りでない。

    今回は最新のバージョン(3.4.0)をインストールした。

    3.4 IR Kernelをインストールする

    IR Kernelなるものを使うとJupyter NotebookでRのカーネルが使えるとのこと。

    JupyterでRを使う。 - Qiita
    http://qiita.com/piruty_joy/items/498ee16de62879e5a949

    上の記事はMacでのインストールだったので以下を参考にした:

    Installation · IRkernel|
    https://irkernel.github.io/installation/

    Rのコンソール上で以下を実行する:
    install.packages(c('repr', 'IRdisplay', 'evaluate', 'crayon', 'pbdZMQ', 'devtools', 'uuid', 'digest'))
    devtools::install_github('IRkernel/IRkernel')
    

    カレントユーザーのみの使用なので以下を実行。
    IRkernel::installspec()
    

    Jupyter Notebookを起動して、右上のNewを押すと、選択肢にRが増えている。



    これでJupyter NotebookでもRが使える。