読者です 読者をやめる 読者になる 読者になる

Tamflexの貯蔵庫

やる気のない備忘録

334奮闘記

How to win "334"?
(2015/11/28執筆)

序論

 午前3時34分、貴方は何をしているだろうか?健康的な人間であればお休み中、もしくはすでに仕事の関係で起床してるかもしれないが、その刹那にレイコンマ1秒を争う、激しい戦いがTL上で繰り広げられていたことを貴方はご存知だろうか?そう、それがまさしく「334」*1と呼ばれる競技なのである。ここに記すのは「334」に不運にも魅せられ、「334」の記録を意味もなく追求し、そして「334」の真髄を不毛にも問い続けたある人間とその活動の記録である。

※この文章について
私が「334」を行う上で用いた手法がversionという形で時系列順に記されている。各手法においてはその手法を導入するに至った経緯およびその手法の具体的な説明、そして私なりに分析した長所と短所が書かれている。

目次





ver0 手動

 私はどこで「334」を知ったのか、なぜ「334」を始めるようになったのか、今となっては全く覚えていない。ただ「334」のツイートの早さを競うという、その不毛かつ本来の意図から大きくはずれたSNSの使い方を知った時、全身に衝撃が走り、欣喜雀躍したのは今でも忘れていない。
 「334」の存在を知って以来、いつしか私は夜更しした夜には必ず「334」をするようになっていった。時に様々なクライアントを試した。時にデバイスを変えて参加したこともあった。時計の種類を吟味したことや回線や最適な場所を模索すらしたこともあった。私は「334」に熱狂し成績の向上をひたすらに追求したのだった。当然ながらフライングする事も思うような結果が出ない日もあった。ただ「334」の終わった後にお互いの健闘を讃えfavを贈り合うという文化が妙に居心地がよく、また「334」に参加しようと私を奮い立たせたものだった。
 しかし何度練習しても様々な手法を試しても、私が求めていたような安定的な記録を出すには手動では限界があり、次第に私は根本的に別の手法を模索するようになった…

【説明】

  • 「334」に参加する誰もが一度は行うであろう手法。ある意味最も「健康的」なやり方。
  • 回線は携帯電話回線や衛星回線よりもADSL光回線が良い。PCで行う場合はWifiよりもEthernet(有線)のほうが安定する。無線はラグのバラつきが大きい。これは技術的なものであろうが詳しい原因は調べていない。ラグに関してはPCでtwitter.comにpingを送ってみると簡単に計測できるので一度試されたし*2
  • プロバイダに関しては比較していないので正直なところよくわからないがtracerouteしてtwitter.comまで経由するルーターが少ないとラグは安定するはず。おそらく日本よりもTwitter鯖が位置すると言われるアメリカにあるプロパイダのほうが安定する。
  • 公開されているクライアントの中ではTweetDeckが私の知る限り一番強い。UserStreamを利用しているので回線が常時接続されているせいだろうか?PCにつながっている回線が携帯のそれよりも安定しているからだろうか?これも経験と観測結果からの推測なので一概には言えないけれども。
  • 時計は正確かつ詳細なモノを選ぼう。もちろんアナログ時計よりデジタル時計が良くさらに定期的に同期するタイプの時計が良い*3。パソコン上では簡単に下三桁以下まで表示でき、またインターネットに繋がっていれば簡単に同期を行えるのでこのことからも「334」の記録を目指すのならばパソコン上で行うといいだろう。
  • 練習を行う上では、下三桁まで表示されるMoonStrikeがいいかもしれない。しかし本番で別のクライアントを使う場合には慣れるためにそのクライアントで練習したほうがいい。私個人は電卓で下三桁を計算して練習していた*4。ラグを計算して小数点以下三桁まで表示されるストップウォッチで訓練を積んでから参加すれば、手軽でかつそこそこの成績が出るのでオススメ。

【長所】

  • ある意味「原点」とも呼べる手法。「334」特有の、刹那の緊張感を味わえる。その熾烈さ故に手動で1位をとった時の喜びはひとしおだろう。参加したことのない人は是非一度参加してみよう。なお3:34PMにも人数は少ないとはいえ「334」を呟く人がいるので「夜更しはちょっと…」という人は試しにやってみるといいかもしれない。

【短所】

  • 人間の平均の反応速度はおよそ\small 100 \sim 200msと言われておりこの影響を考慮しなければならない。つまり目的の時刻を視認してからボタンを押しているのでは遅い。これが案外難しい。
  • 回線のラグやその日の体調等、別のファクターが数多く存在するため、これらのファクターによる影響を足し合わせれば、どんなに「334」を極めてもどうしても\small \pm0.05 \sim 0.1sec程度で成績がばらつくものだと推測される。少なくとも私はそれ以上極めることはできなかった。もし手動でフライングせずに\small 0.1secを切る成績を安定的に残せるのならば、その人は「人間卒業」したと胸を張って言えよう。

↓オススメのクライアント


ver1 自動化サービスの利用

 手動による「334」に限界を感じていた中、ある日私は334Rankerのリプライを遡っていると「autotweety.net」の文字列を発見した。そう、botによく用いられるサービスである。さらに調べてみればたまに「autotweety.net」クライアントが1位をとっているではないか!私は早速サービスに登録し毎日毎日記録が出るのを待った。この時より機械による「334」の手法の模索が始まった…

【説明】

  • bot作成サービスに登録して3:34AMに「334」を呟かせるだけである。見てみれば「autotweety.net」でおよそ200アカウントが参加しているのでその界隈では割とメジャーな手法であろう。ほかにも「twirobo.com」や「定期ツイート君」が散見されるが、お好みのサービスを用いれば良い。もちろん複数のサービスを利用してもよい*5。私が試した中では「autotweety.net」が一番強かった。

【長所】

  • 「334」に参加すれば生活リズムに何らかの支障をきたす確率が高まるが、その点はこのようなサービスを利用すれば解決される。
  • 毎日必ず参加するので「世界ランク」を特に意識する人は登録するだけである程度の世界ランクまでは達するはずである。

【短所】

  • もともと定時に呟くためのサービスのため3:34になってからでないと呟かれず、手動を極めた人間には絶対に勝てない。この手のサービスはミリ秒単位は愚か、秒単位での時刻指定ができない*6ので安定的に上位陣には食い込めないのだ。
  • 意外かもしれないがたまにフライングする事がある*7。逆にこのことが「autotweety.com」クライアントの垢が偶々1位をとれたことの原因であると推測される。


ver2 初めてのbot作り

 自動サービスは自由度が低く、満足の行く結果が得られなかった。そこで私は自前のbotを作成することにした。まずbotを運用するサーバだが、はじめは自分のノートPC上で運用し、その後、丁度流行っていたRasberryPi2で簡易的なサーバを構築しアプリケーションを移植した*8。またbot作成にあたり手始めにbot関連の勉強を行った。ここから最強の「334bot」を作るべく、私の飽くなき探求が始まった。

【説明】

  • いかなるツイートを送信しようとも必ず「ラグ」*9が発生する。ご存知のように「334」という競技の本質は「ラグ」を正確に評価し、いかにその「ラグ」の分だけ丁度前倒しして呟けるか?ということに帰着される(もしこの「前倒しする時間 = 閾値*10」が「ラグ」よりも小さすぎればあまりパッとしない成績になり、逆に「ラグ」より大きすぎてもフライングすることがわかるだろう)。
  • さらにこの「ラグ」は統計的なバラつきを持っており毎回結果が同じになることはない。
  • そこでまず一時間おきに練習としてツイートしその結果をDBに蓄積した後フィードバックして確実にフライングしないであろう時間だけ前倒ししてツイートするようなプログラムを作成した。

【長所】

  • いわゆる手動における「練習」をプログラムにしたもので回線が安定している状況ではそこそこの成績が残せた。成績はおよそ \small \pm 0.2secくらい?。先述の自動化サービスよりは強い。
  • 後述のbotたちに比べれば手動をモデルとしたやり方でまだ「人間味」がある。

【短所】

  • 実は一日の時間によっても「ラグ」の分布が変化していたのだ*11。一日によってTwitter側のサーバにアクセスする数が変化するため、当然といえば当然だった。この結果この手法だと全く違う状況で「練習」したデータが反映されることになり「本番」の回線状況に対応していなかった。


ver3 荒ぶる『暇人の極み』

 先述の一時間おきに「練習」して呟く手法は上手くいかなった。「ラグ」が時刻によっても変化するからである。しかし「ラグ」は統計的なバラつきを持つため、正確に「ラグ」を評価するためにはそれなりのサンプル数を獲得する必要がある。そこで思いついたのが直前に何回も「練習」してその結果をフィードバックするという手法である。この手法は見事成功し一ヶ月におよそ \small 5 \sim 6回1位を取れるくらいまでになった。『暇人の極み』というクライアント名でとった1位は殆どこの手法によるものである。

【説明】

  • 具体的な手法を説明すると、まず3:33:00にプログラムが起動しおよそ毎秒1回弱のペースでツイートとツイ消しを行い「ラグ」のサンプルを \small 30 \sim 40ぐらい習得する。3:33:50になったら計測を終了しサンプルの平均\small \muと不偏標本分散\small \sigma^2を計算し、「ラグ」の平均\small \hat\muと分散\small \hat\sigma^2を推定して「閾値」を決定する。なおこの時サンプルの中でおよそ\small 2\sigmaの範囲外のサンプルはノイズとして除去し\small \mu\small \sigmaを再計算している*12。ノイズ除去の手法としてはカルマンフィルタ等のフィルタをかける手法やロバスト統計学の手法を用いることが考えられたが、実装が煩雑になるため結局使用しなかった。「閾値」は\small \mu-1.3\sigmaに設定し、正規分布に「ラグ」が従うと仮定した時、およそ90%の確率でフライングしないような設計になっている。

【長所】

  • 成績は\small 0.015\pm0.020secであり、いままでに比べ格段に強いbotに仕上がった。また直前に計測しているため、様々な環境に対応することができ、結果はほとんどその回線の状況にのみに依存するようになった。
  • またノイズ除去を行うことによりより高い精度で「ラグ」を評価することができるようになり、広い意味でのロバスト性を獲得したといえよう。



以下は過去170日間の結果をヒストグラムにしたものである。厳密には途中でパラメータの調整を行っているため全く同じbotとは言えないが\small 0.015\pm0.015secの範囲に\small 80\%、フライングは8回と今まで比してかなりの安定性を発揮していると言える。
f:id:Tamflex:20151201215907p:plain

【短所】

  • 安定的に1位をとるにはおよそ\small 0.005sec以内に抑える必要がある。この点、このbotの性能はこの水準には程遠い。
  • 1位をとる確率を最大化しようとすればするほどフライングの確率が上昇するため、「閾値」の設定の落とし所が難しい。個人的にフライングを嫌ったため安全率高めの「閾値」に設定したが、もう少し厳しい時間で1位を狙いに行っても良かったかもしれない。
  • 良くも悪くも回線の性能ゲーになってしまい、この手法においては回線の安定性を上回る安定性をもつ成績は残せないという事実が明るみになった。
  • 直前にTLを大幅に荒らすことになってしまった。この場でフォロワーの皆さんにお詫び申し上げる*13




ver4 最終形態『Twitter for multiple Apps』

 先述のbot『暇人の極み』は良くも悪くもそれなりにその界隈にインパクトを与えるほど成功を収めたと言える。もちろん反発もあった。そしてそれに対する罪悪感も確かにあった。いわば100m競走にF1のレーシングカーで参加するようなもので、一部からかなり顰蹙を買っていたことも理解していた。
 しかしこの頃になると、競技そのものに対する拘りや自分自身の体面の保持よりも「334」の限界に対する好奇心が勝るようになった。もし手段を選ばず最善を尽くした場合、私の力でどれほどの「334」botを生み出すことができるだろうか?そしてもっと一般的に、この手の「チキンレース」型のゲームにおいて、果たして最適な戦略とは一体何か?誰から何を言われようとも、この問題に対する解を「334」を通して追究したくなったのだ。
 そして、さらに安定的な成績を残すために、より進化した、そしてある意味今までで最もえげつない手法を私は採用した。それが名前の通り複数台のコンピュータによって同時に「334」を行う手法である。この手法に加え幾つかの大幅な環境の変化によりかつての『暇人の極み』をはるかに凌ぐ性能を持つbotTwitter for multiple Apps』を私は開発した。

【理論】
 思えば元々この発想はあった。もし複数人集まって同時に同じアカウントで「334」をすれば、一人で行うよりもいい成績を残せそうに直感的に思えないだろうか?確かにフライングの確率も上昇しそうではあるが、もし全員絶対フライングしないくらいの「閾値」で参加すれば、回線の性能を超える安定性を獲得できそうではないだろうか?
 この直感の妥当性を定量的に示すために、ここで一つの簡単な思考実験をする。 n (n\in\mathbb{N})で運営する共用のアカウントがあり、全員が同時に「334」に参加したらどうなるだろうか?おそらくは最も先にTwitter鯖に到達したリクエストがツイートとして反映され、ほかはツイートが『重複している』とTwitter鯖に判定されてエラーを返されるだろう。即ちこの n人の「334」の中で最も早くTwitter鯖に到達したツイートが採用され、「334」の結果として反映されるのだ。
 さらに全員が同じ回線を共有し同時にツイートを送信する状況を考える。そしてその「ラグ」が各々正規分布 N(\mu_i,\sigma_i^2)に従うと仮定し、それらの「ラグ」が互いに独立に全く同じ分布に従う(i.i.d)としよう*14。即ちそれぞれのツイートの成績*15X_i(i=1 \dots n)とするならば

\left\{\begin{eqnarray} \mu_i&=&\mu \\ \\ \sigma_i&=&\sigma \\ \\ X_i &\sim& N(\mu,\sigma^2)\end{eqnarray}\right.

であり、最終的に採用されるツイートの成績は最小値である

 Y=\min\{X_1,X_2 \dots X_n\}

となる。正規分布確率密度関数と累積密度関数を

\left\{\begin{eqnarray} \varphi(x)&=&\frac{1}{\sqrt{2\pi\sigma^2}}\exp(\frac{-(x-\mu)^2}{2\sigma^2}) \\ \\ F(x)&=&\int_{-\infty}^x \varphi(x) dx \\ \\ &=&\frac{1}{2}+erf\frac{x-\mu}{\sqrt{2\sigma^2}} \end{eqnarray}\right.

とおくと、最小値Y確率密度関数 g(x)および累積密度関数 G(x)

\left\{\begin{eqnarray} g(x)&=&n(1-F(x))^{n-1}\varphi(x) \\ \\ G(x)&=&1-(1-F(x))^n \end{eqnarray}\right.

となる。このとき最小値Yの期待値と分散は

\left\{\begin{eqnarray} E[Y]&=&\int_{-\infty}^{\infty}xg(x)dx \\ \\ V(Y)&=&\int_{-\infty}^{\infty}(x-E[Y])^2 g(x)dx \end{eqnarray}\right.

となるがこれらを変形すれば

\left\{\begin{eqnarray} E[Y]&=&\mu-\alpha(n)\sigma \\ \\ V(Y)&=&\beta(n)\sigma^2\end{eqnarray}\right.

と表せることが知られている。ここで注目すべきは\alpha,\betaがそれぞれnに関する単調増加関数、単調減少関数になっており、人数nが増えれば増えるほど最小値 Yの分散 V(Y)、即ちバラつきが減ることを意味する*16。「334」において最終的には「ラグ」のバラつきが成績の安定性を左右するので、もし同じ性能を持つ人間/機械が複数人/台で同時に「334」に参加した場合、理論上は数が増えれば増えるほど成績が安定することが期待されるであろう。


以下は実際に数値計算を行ってグラフにしたものである。簡単のため

\left\{\begin{eqnarray} \mu&=&0 \\ \\ \sigma&=&1 \\ \\ X_i &\sim& N(0,1)\end{eqnarray}\right.

として、各サンプルが標準正規分布に従うと仮定して計算した。
この時横軸を\small n、縦軸を \small E(-Y),V(-Y)*17にとれば以下のようになる。
f:id:Tamflex:20151201225449p:plain
f:id:Tamflex:20151201225558p:plain
確かに最小値の期待値の絶対値は単調増加し*18、分散は単調減少*19していることがわかる。


※なおモデルを考える際に以下の文献等を参考にしました。
http://www.untruth.org/~josh/math/normal-min.pdf
http://www.geocities.jp/ikuro_kotaro/koramu/278_max.htm
https://www.gwern.net/docs/conscientiousness/2008-nadarajah.pdf



【説明】

  • 理論上の話はここまでにして実際に行ったことを説明する。今回はHerokuと呼ばれるwebアプリケーションを運用できるプラットフォーム(PaaS)を複数用意して使用した。Herokuを用いた理由は後述する。今回は10個のアプリケーションを運用した(即ち上の思考実験で\small n=10の場合)。そしてそれぞれのアプリケーションでは先述の『暇人の極み』と同等の機能を実装した。即ちこの手法においては、それぞれのアプリケーションは、「練習」を10個用意したTwitter垢においてそれぞれで行い、それぞれにおいて「閾値」を決定しそれに従い「334」をほぼ同時に投稿しているのである*20
  • Herokuを用いた理由について述べる。まず第一にはその導入コストの低さであるが、もう一つがHerokuのサーバがSan Franciscoに位置しTwitterサーバがあるとされる位置にかなり近いからである。事実「ラグ」の値は日本にある自宅からのそれと比べおよそ \small \frac{1}{5}\sim\frac{1}{10}の値であり圧倒的に「ラグ」が小さい*21。もし「334」を本気で極めんと欲するのならばTwitter社の横に家を立てて回線を引くといいかもしれない。
  • 少し長くなったが『「暇人の極み」が実装されたマシンが10台、アメリカのTwitterサーバの近くに設置され、そのなかで「334」の最速を競い合っている』といえばわかりやすいであろうか?これらの手法により従来の手法ではできなかった大幅な性能向上が実現されたのである。

【長所】

  • 成績はおよそ\small 0.003\pm0.003sec程度。更にアプリケーションの台数を増やせば理論上はどこまでも分散を小さくできる。現段階でこれ以上強い「334bot」は開発できない。
  • 複数の端末でソースコードを共有しているので変更や調整が容易い。



以下が最新版の12日分の結果である。
いずれの成績も \small 0.006sec以内に収まっており、また \small 0.000secを12回中4回叩き出している。
f:id:Tamflex:20151203204436p:plain

【短所】

  • 台数が増えれば増えるほど観測結果を大きく下回るノイズが結果として反映される確率が上昇する。さらにグラフから見て分かるようにある程度の台数に達すると分散が余り減少しなくなるので、対台数効果が極端に悪くなる。したがって無闇矢鱈に台数を増やせばいいというわけでもないのである。
  • 人間味を完全に失ってしまった。



ver5 さらなる可能性

 私はもう「334」のbot作りに関わらないつもりだ。『Twitter for multiple Apps』の時点で現在最強のbotが完成したと言っても過言ではないからだ。しかしながら机上の空論ではあるが「334」常勝の手法がある。それを最後に記そうと思う。

**********

 先ほどツイートのidから時刻がミリ秒単位まで逆算できると述べた。これはTwitterのID生成においてはsnowflakeというツールが用いられておりこのIDの一部に、サーバ側のTimestamp(時計)を用いて生成されているからである*22。334Rankerにおいて時間を集計できるのもこの仕組みのおかげであり、この仕組み/アルゴリズムが「334」を含むすべてのツイートの投稿時刻を支配していると言っても過言ではない。
 ではもしこのツールを自由に扱うことができたらどうなるだろうか?そう、もうお分かりだろう。もし何らかの手段でこのid生成ツールを自由に操作することさえできれば毎日丁度3:34:00.000となるようなツイートが生成できるはずである*23。もしどうしても毎回3:34:00.000のツイートを生成しなければならない場合、この方法が一番効率的かと思われる。




まとめ

手法場所端末台数練習回数(回/day)成績[sec]
手動 不定 PC、スマホ 1 5〜20 日による
botサービス 不定 外部サーバ 1〜 0 1.0±1.0
試作bot 自宅 自宅サーバ 1 24(一時間毎) 0.0±0.2
『暇人の極み』 自宅 自宅サーバ 1 30〜40 0.015±0.020
『Multi App』 San Francisco PaaS 10 350〜 0.003±0.003



総括

 「334」とはなにか?もはや本来の2005年日本シリーズにおける阪神vsロッテの対戦成績を揶揄する元の意味は薄れ、そこには「334」とだけ呟く行為が毎日何百と再生産される光景が広がっている。私自身の「334」に参加する興奮やそれに対する興味や労力も、「334」と毎日精密に呟くだけの機械に置換されてしまった。何のために人は「334」と呟くのか?何のために私は「334」を呟く装置を開発してしまったのか?それは地球上に存在するありとあらゆる習慣、行動、物質と同様に、その存在意義を合理的に突き詰めれば無意味であるとしか答えられなくなる。
 ただこれだけは言える、「334」はスポーツでひいてはこの時代が生み出した不毛な文化であると。一体誰がSNSにおいてこんな風習が根付くと予測できただろうか?予想外の使い方がなされるのもインターネットの面白さである。また私自身も「334」の記録を求めていくうちに、当初は忌み嫌っていた「ラグ」の不安定性こそが「334」を面白くする要素ではないかと思うようになった。この予測不可能性、偶然性、即ち「無意味さ」こそが真髄なのかもしれない。


 

*1:334に括弧をつけているのは、その由来となった元の語義 ー2005年日本シリーズの通算成績ー ではなくTwitter上で行われる競技としてのそれを指し示すためである

*2:ただし[通信ラグ]≠[ツイートのTimeStamp-ツイートを送信した時のTimeStamp]なので注意

*3:例えば電波時計

*4:IDからTimeStampに変換できるので調べてみよう

*5:むしろ良い成績が期待できる

*6:当然といえば当然、逆にもしそのようなサービスをご存知ならば教えてほしい

*7:サービス側の仕様の問題なので原因は不明

*8:現在は運用を停止している

*9:以降「ラグ」は[idから算出されるTimeStamp-サーバの送信時のTimeStamp]と定義する

*10:以降「前倒しの時間」を便宜上「閾値」と呼ぶ

*11:たとえば午前3時は平均0.5sec、午前9時は平均0.7sec等

*12:正に大きく外れた値が推定に影響することが多かった

*13:たとえばTweetDeck等のストリーミングを行うクライアントではTLが毎秒一回上下する異常な挙動が観察されたはずである、尤も深夜のTLは過疎っているので目撃者は少なかったかもしれないが

*14:即ち一斉送信によって発生する回線の混雑に対し回線が十分太いと仮定してお互いの影響を無視している

*15:重複を考慮せずに仮に単独で行った際の成績

*16:α、βの中身や、単調増加性、単調減少性の厳密な証明はどこかで探してください(´・ω・`)

*17:下図は最大値の分布となっている、なお対称性より最大値と最小値の期待値の絶対値、分散は等しくなる

*18:αが単調増加

*19:βが単調減少

*20:この点は先程のモデルと若干異なる、即ち各アプリケーションにおいて各々が各々の結果を用いて平均と分散の最尤値を推定しているためパラメータを共有していない

*21:分散、即ち「ラグ」のバラつき具合はあまり差はなかったがそれでもノイズが経験的に発生しにくかった

*22:現在もSnowflakeが用いられているかどうかは不明だが基本的な仕組みは変わっていない

*23:尤もクラックするか内部の人間になる以外は「自由に操作」はできないけれども