霞と側杖を食らう

ほしいものです。なにかいただけるとしあわせです。[https://www.amazon.jp/hz/wishlist/ls/2EIEFTV4IKSIJ?ref_=wl_share]

Jリーグコンペの後日譚々

結論だけ、書く。  

失敗した失敗した失敗した失敗した失敗した失敗した失敗した失敗した    失敗した失敗した失敗した失敗した失敗した失敗した失敗した失敗した    失敗した失敗した失敗した失敗した失敗した  

あたしは失敗した失敗した失敗した失敗した失敗した失敗した失敗した    失敗した失敗した失敗したあたしは失敗した失敗  

今は、西暦2018年の、12月13日です。  

  

 我々は二つの大きな失敗を犯した。我々というのは、大学の後輩と二人でチームを組み、【学生限定】マイナビ × SIGNATE Student Cup 2018: Jリーグの観客動員数予測 のコンペ(Jリーグコンペ)に参加していたためだ。私が基礎分析や特徴量の考案、最終決断等を担当して、チームメイトにモデルのチューニングやコーディングを担当してもらった。二人とも、このコンペが、まともに参加する初めてのコンペであった。最初は、経験値を積むくらいの目的で軽い気持ちで参加していたのだが、順位争いができるところまで来て、躍起になって戦った。以下で、このJリーグコンペに参加した後日譚、我々の二つの主な失敗と我々の解法について述べる。

 

一つ目の失敗

 一つ目の大きな失敗は、live期間の欠損値(未来の値)の代入に関するミスだ。二つの特徴量について、代入のコードにミスがあった。正しく代入できていなかったのだ。特徴量の代入に関して、確認をするべきであった。このチェックをする余裕が無かったのは、後で述べるが、特徴量として使用していたgoogleトレンドの再現性の確保が完璧にできないことに、コンペの最終盤で気付いて、思考のリソースがそちらに完全に奪われていたためであった。もし、次にデータ分析コンペに参加したときは、欠損値の代入後のチェックを怠らないようにしたい。  

 

二つ目の失敗

 最後に提出するモデルを選ぶとき、2つのモデルで迷っていた。googleトレンドを使用しているモデルと、それを使用していないモデルだ(モデルの説明については後で述べる)。最後に選んだのは、使用する方のモデルだった。これが二つ目の失敗だ。こちらのモデルを選んだのは、提出したときに返ってきたスコアがそちらの方が良かったからだ。ぶっちぎりの1位のスコアが出てしまったのだ。浮かれてしまった。勝負は熱く振る舞っても思考は冷静に保たなければならないというのは分かっていたはずなのにだ。googleトレンドありのモデルの悪かった点は、googleトレンド値の予測をした上で、観客数を予測しないといけない点だ。googleトレンドは未来に余計なイベントが起きてしまうと全然違う値になる。今回で言えば、第33節でトーレスが得点したことや、第34節目前に神戸がビジャを獲得したことは予想外のイベントであった。このあたりが、googleトレンドの予測を大きく外した原因に思える。live期間は2節分だけで、2週間程度なので、そこまで、大きな変化は起きないだろうと高を括っていた。もう少しlive期間が長ければ外す決断をしていたかもしれない。外す可能性も考えながらも、googleトレンドありのモデルを提出する決断をしてしまった。  当たれば、とてつもないスコアが出るのではないかという甘い蜜に唆されて、冷静さを欠いてしまった。  

 

失敗と教訓

 以上の二つの失敗を反省できたのは、test期間による暫定順位は1位だったのに、live期間を含めた最終結果は47位と暴落していたからだ。live期間のスコアも、そんなはずないと思うくらいの低さだった。そんなに過学習してしまったのかと疑ったのと、もう一つのモデル(googleトレンドなしのモデル)のスコアも気になったので、予測値と実際の値で評価し直してみた。このとき、特徴量の代入にミスがあることに気が付いた。正しく代入をし直した結果、提出したモデル(googleトレンドありのモデル)でスコアを出すと、test期間は0.181(これは暫定順位に載っていたものと同じ)、live期間は0.221であった。つまり、第一の失敗を克服しても、入賞可能圏内には届かない。ところが、googleトレンドなしのモデルで試してみると、test期間は0.189、live期間は0.172となった。この計算結果を知って、脳みそが凍りついてしまった。第一の失敗と第二の失敗を両方とも犯していなければ、スコアでの評価は二位になっていたのだ。もちろん、このスコアが出ていたところでコードレビューやレポートチェックがあることも分かっているし、歴史にIFはなく、今更どうすることもできないことも分かっている。ただの負け犬の遠吠えにしかならないのも分かっている。分かっているけれど、できることなら、一か月前の自分宛てにDメールを送信したい。ママーと叫びながら、電子レンジにバナナを突っ込んでボタンを連打した。  

 こんな失敗をして、ただただ嘆いていても仕方がない。冷静さを欠いてはいけない。ブレスレットブレスレット。今回の件から我々が得るべき第一の教訓は、欠損値は埋めた後、要約統計量やプロットによって、チェックをするべきだということだ。それを怠ったため、第一の失敗が生じた。第二の教訓は、勝負事で冷静さを失ったら負けてしまうということだ。びっくりするような良いスコアが出たからといって浮かれずに、予測を使った予測の危うさ、とくに最初の予測が精度を担保しきれない場合の予測の危うさについて、もう少し冷静に考慮できていれば、第二の失敗は防げたかもしれない。どちらの失敗もコンペ経験の浅さが大きな原因だと思われる。そういう意味で言えば、当初の目的であった経験値を積むということは、かなり達成されたと言えるのではないだろうか。ガリレオフィガロ~。  

 

その他の反省点

 コンペ経験の無さゆえ、できてないことが他にもいくつかあった。  

 公開ランキングでの戦い方もよく分からなかった。早めにランキングで高いスコアを叩き出してしまうと他の強い方々が奮起してしまったら怖いなんて思ったりしたので、最終日に狙い撃ちした(他にも同じことを考える人はいるだろうと思ったし、実際いた)。フォーラムでの議論の仕方もよく分からなかった。自分のやっていることを公開して議論できるってすごいと思った。個人的に機械学習の技能に全く自信がなかったので、ドメイン知識を増やして、観客(潜在的な観客も含め)の気持ちになりきって、特徴量を考案してコンペを戦うしかないと思っていた。自分のアイデアを渡したら、機械学習つよい人たちにボコボコにされてしまうだろうと怯えていた。ランキングの狙い撃ちなどせず、フォーラムで議論できるくらいに強くありたいと思った(一方で、制度設計の問題でもあるように思わなくもない。それらを行うインセンティブがあまり働かないとは思った。強いてメリットを言うなら、フォーラムに投げることで自分がやっていることが正しいかを他人の反応でチェックできるということは挙げられる。それでも、我々のようにコンペ経験浅い人には難しい)。  

 また、再現性の確保をこまめに確認するべきであった。コンペ終盤になって、自分たちが入賞候補に入れそうだと分かって、レポートの準備を始めてから、googleトレンドが完璧に再現できないことに気付いた。スクレイピングに時間がかかるため、手元に保存していたファイルでずっと作業していた結果、スクレイピングから再現しなおすと完全に再現できないことに気付くのが遅くなってしまった。googleトレンドが完璧に再現できない点については、何度か実験してみた結果、おそらくgoogleのサービス側でわずかに変化してしまうということが分かった。大きく値が変わることはないが、取り直してみるとわずかに異なる値が得られた。このことについて、コンペ最終盤の締め切りギリギリまで悩まされた。このことをレポートに盛り込めばなんとかなるだろうというピンチの中での僅かな楽観的な安堵を求めて藁をもすがる気持ちもあって、googleトレンドありのモデルを選択してしまった。再現性のチェックもコンペでは重要だと気付かされた。
  

 我々の解法

 ヤムチャ目線でフォーラムで何もできなかった分、ここで我々の解法について書いていく。手法はXgboostを用いているが、これはチームメイトが担当していたので、とくに、特徴量の説明について詳しく書く。
 提出したスライド8枚を以下に載せる。

f:id:moratoriamuo271:20181213022503j:plain
スライド1

f:id:moratoriamuo271:20181213022558j:plain
スライド2

f:id:moratoriamuo271:20181213022637j:plain
スライド3

f:id:moratoriamuo271:20181213022700j:plain
スライド4

f:id:moratoriamuo271:20181213022725j:plain
スライド5

f:id:moratoriamuo271:20181213022746j:plain
スライド6

f:id:moratoriamuo271:20181213022803j:plain
スライド7

f:id:moratoriamuo271:20181213022820j:plain
スライド8

 メインとなる仮説はスライド3の下の方に書いてあるような情報が影響するというものだ。マクロに考えるより、ミクロに考えて、各個人が試合を観に行くか行かないかの選択をすることを想像し、その観戦者を積み上げた集計値が観戦者数となると考えればよいと思った。Jリーグによく行く人に話を聞いてみたりして、Jリーグへの熱中度が違うと、観戦の選択に関して、全然異なる振る舞いをするということ(異質性の存在)も理解できてきた。それらを意識しながら、特徴量の考案を行った。
 特徴量の一覧はスライド5とスライド6に簡単な説明や意図とともに載せてある。ここでは、おそらく他の方々が作っていないであろう特徴量についてのみ解説する。ホーム拠点とアウェイ拠点間の距離やチーム別総年俸は思いついている人はいたと思うが、スライド7に書いたように、ワールドカップの影響や災害の影響を考慮した特徴量を作った人はあまりいないのではないだろうか。
 まず、ワールドカップの影響を考慮した特徴量 Wcup_deltaについて説明する。ワールドカップはサッカーの世界最高峰の大会なのだから、情報を入れないといけないと考えた。今回のデータの期間では2006,2010,2014,2018年の4回、ワールドカップが開催されていた。ワールドカップの観客数への影響を調べてみると、ワールドカップ始まる前は観客数が増え、終わると観客数が減る傾向にあるようだ。終わった後に減るというのは予想外であった。メディア露出の増減によるものだという解釈がスライド2に挙げた日経新聞の記事に書いてあったように思うが、他の解釈としてはJリーグを応援している熱烈なサッカーファンがワールドカップ観戦で海外に行くと、そこにお金を使ったり有休を使ったりして、ワールドカップが終わった後、日本でサッカー観戦に行きにくくなるのではないかというものを考えた。他にも解釈は考えたが、このへんの解釈は因果推論の担当で、これ以上踏み込むのは止めた。
 さて、このワールドカップの影響の情報をもった特徴量のレシピを説明する。最初に、ワールドカップの開催期間の真ん中の日にそれぞれ1とフラグを立てる(ちなみに、調べてみたら、ワールドカップ開催期間はJリーグは試合を組んでいなかった。そのため、ワールドカップがある年は最終節が12月になっていることが多い。今年もそうであった)。次に、各日がその日から何日離れているか算出する。ワールドカップ前で負の値ならば、1.03をその値でべき乗し、ワールドカップ後で正の値ならば、0.97をその値でべき乗する。値が0なら1でよい。こうして作ったものをプロットしてみると、以下のグラフのような値が得られる。

f:id:moratoriamuo271:20181213032015j:plain
Wcup_deltaの下ごしらえ
こうして、ワールドカップが近づくにつれて増え、終わって時間が経つにつれて減っていくような数列が手に入る。ある程度離れるとほぼ0になっているところが味噌である。この数列を各ワールドカップに対して計算して和をとってWcup_deltaという特徴量は完成する。上に挙げたグラフのような波が4つある数列になる。これを試合の日程とマッチングさせればよい。スライド8にあるように、予測に結構効いている。
 次に、災害の影響を考慮した特徴量 disasterについて説明する。2011年の東日本大震災の影響がまず最初に思い浮かんでいたが、これを盛り込む方法がなかなか思いつかずにコンペ終盤に差し掛かっていた。特徴量考案のために、マッチレポートを読んでみたりしていたら、死者が出る規模の自然災害の後の試合では、試合前に追悼が行われることに気付いた。そこで自然災害、とくに死者が出るレベルの災害は観客数の減少させるはずで、死者数はその災害の規模の情報を持っているという考えに至り、これを自然災害から時間が経つにつれ、減衰していくような特徴量を作って、その地域とスタジアムにマッチさせれば上手くいくというアイデアが思い浮かんだ(そういえば、今年の漢字は「災」に決まったようだ)。
 このアイデアを特徴量に落とし込むレシピはWcup_deltaとほとんど似ている。ただ、災害が起きる前は、通常の大雨なら予報である程度の情報が漏れているかもしれないが、地震ゲリラ豪雨、死者が出るような災害であれば、予想ができないため情報がない。この点がWcup_deltaとは異なる。まずは、Wikipediaの日本の災害リストから、死者が出ている自然災害をピックアップし、災害発生日(死者数がある程度分かっているであろう日にち)と死者数とその地域の情報を抽出する。
f:id:moratoriamuo271:20181213041006p:plain
災害情報
この地域とチーム(ホームとアウェイ別)で照合して、災害発生日翌日に死者数の値を代入する。あとは1日経つにつれて0.98を乗じていき、数列を作って、試合日とマッチングさせればよい。これもまた、スライド8にあるように予測に効いている。

 以上の2つは、レシピ含め、独創性があるのではないかと思っている。1.03や0.97, 0.98のような値は減衰率と我々は呼んでいた。この考えは他の特徴量にも使っている。値は、効果の影響がどれくらい残るかを想像しながら、何通りか試してCVで決定した。減衰率の発想は、経済学の動学モデルで、割引現在価値や利子率の考慮をよくするので、思いついた。特徴量考案は、私が社会科学の畑の出身で(チームメイトは工学の畑出身)、人間の選択について考える訓練を積んでいたからか、やりやすく、思い付いた特徴量を入れると予測精度が予想通り上がっていく様はとても痛快であった。人間の行動に関する予測や分析は社会科学や人文科学の人間をチームに入れると良いのではないだろうか。画像のコンペや自然科学寄りのコンペでは、少なくとも私は戦力になりにくそうだと思った。そう思ったし、今回はチャンスだったんだと思った。勝ちたかった。ドラゴンボールはどこにあるのだろうか。

我々のモデルの限界と未実行の解法

 以上のような解法で今回のコンペに挑んだ。googleトレンドについては上に書いた通り限界なのは分かっている。他に、終盤の優勝争いや残留争いの情報を明示的に取り込めていなかった。順位争いは入れていたが、優勝争いと残留争いの効果を明示的に取り込めるような特徴量が思いつかなかった。とくに今回残留争いが激しかったので、それを組み込めれば、もっと良い予測精度を叩き出せただろう。live期間は33節と34節なのだから、そこにもっと思考のリソースを割くべきだった。シーズン途中に加入してきた選手の情報を上手く組み込む特徴量があれば良かったのだが、それをgoogleトレンドに頼ってしまった。他にもっと良い策があったかもしれないが思い付かなかった。
 未遂に終わった解法が一つあって、それは、マッチレポートをスクレイピングしてテキストマイニングを行うというものだ。災害の特徴量を思いつくきっかけになったのはマッチレポートであったと書いたが、あれを早いうちに気付いて、マッチレポートから単語の頻度分析など行えば、特徴量考案に一役二役買っていたかもしれない。これを実行する時間と余裕がなかった。発想としては面白いし、こんな解法を思いついた人はいないのではないかと思い、ここに記しておく。あとはタイムマシンの作成か。

終わりに

 つらつらと後日譚を書いてきましたが、こんな量を一気に書きあげてしまうくらい反省しており、反省から大反省へ、そしてその大反省は大猛省へと昇華させました。この大猛省を活かして、今後の人生を歩んでいきたいと思います。また、データ分析コンペの難しさ(仕事しながらコンペいくつも参加している人の凄さに驚きました。半端ないって。)に加えて、面白さ、奥深さを知ることができました。やってみないと分からないですね、これは。食わず嫌いせずに参加してみてよかったと思っています。
 この機会を与えてくださったSIGNATEさん、マイナビさん、ありがとうございました。感謝です。そして、入賞した皆さま、おめでとうございます。参加した皆さま、お疲れ様でした。もしもお会いする機会があれば、後日譚をお話ししたいと思っています。さらば読者よ、命あらばまた他日。元気で行かう。絶望するな。では、失敬。

蛇でいてくれてありがとう

 スイス育ちの方が、日本はハイコンテクスト文化の国で、日本で付き合ってた恋人たちとなぜ上手くいかなかったが分かったなんて言っていたツイートがバズっていた。

スイス育ちの人が日本の人とコミュニケーションが難しいという理由に共感する声「人にものを教えるときに気をつけたい」 - Togetter

ここでは文化人類学者のホールの研究が取り上げられているが、少し気になってgoogle先生に聞いてみると、その研究には実証的根拠はなく、むしろ追試によって実証的に否定されているのだとか。

「日本文化はハイコンテクスト」には実証的根拠がない - 旧版こにしき(言葉、日本社会、教育)※2018年4月、新ブログに移行済み

どのように実証的に示すのか、手法が気になるところではあるが、追試の論文についてまだ確認していない。

 日本がハイコンテクストな文化の国なのかどうかは知らないが、遊びの会話においてハイコンテクストだととても楽しい(「遊び」と書いたのは、遊びでない議論などではローコンテクストから積み上げるべきだからだ)。遊びの会話において、個人的には、どちらかというとツッコミよりボケの役割を負うことが多いのだが、会話でボケるとき、相手がボケの内容を知識として持っていることを期待してボケる。知らないであろうと予想することはボケても伝わらないので(スベるので)、思い付いてもお蔵入りになってしまう。そんなきわどい予測の中で、ハイコンテクストが共有できたとき、得も言われぬ快感が生じる(これに似た話は前回の記事で少し書いた)。自分に文化圏が近い人との会話において、相手の持っているであろう知識の推測はしやすい。会話の中で、仲良くなっていく過程で、相手の関心分野などから推し測っていけばよい。しかし、留学生や年の離れた人など、自分の文化圏と離れて文化圏に属している人の知識の推測は難しいし、そもそも相手の持つ知識自体を自分が知らないことが多く、コンテクストの共有が困難であることが多い(そんなことや表現力の不足から英語での会話がとても苦しい、ボケとツッコミなんて文化、海外にないだろうし、海外のお笑い文化が気になる)。

 相手の知識や戦略、行動の幅の予測は、バドミントンでも行っている。相手がどの球に反応できるのか、どういうショットを打ってくるのかの推測をラリーの中で、意識的にまたは無意識的にしている。逆に相手の予測を読んで、その予測の外側のショット、つまりフェイントショットを打つ。ダブルスのペアに対しても同様で、ペアがどう動くであろうから、自分はどこにポジションをとるといった行動をとったりする。どうして予測をしているのかというと、予測をして、予測の範囲外を計算から外して、早く速く動くためだ。余計な計算を省くことで、不確実性が多い中で、効率的に動くことができる。

 このような予測による計算の省略は、社会にありふれている。たとえば、左側通行だ。左側を通るものだと予測し合っているから、余計な計算コストを生じさせずに、互いに道を進むことができる。予測と違った行動をしてくると、事故が起きやすい。家の近くの信号がこの前、歩車分離式信号に変わったのだが、変わったばかりで、予測が現実とかみ合ってなくて危ない瞬間を何度も見かけた。車側は横断する信号が赤になったら、次はこっちが青になると予測しているので、歩行者信号のみが青になるタイミングで、進もうとしてしまう。歩行者は歩行者で、赤なのに青になると勘違いして歩こうとしてしまう。

 社会の設計(情報公開も含め)において、人々の予測や期待で以て行動をすることを考慮にいれなければならない。余計な計算コスト(エネルギーや時間)を省くようなデザインならば、各個人が余計な費用を省略出来て、全体として大きく厚生を改善できる。上の信号の話もそうだが、この話でよく思い浮かぶのが、公のホームページのデザインだ。必要な情報がどこにあるか分かりにくい設計のホームページが多い。東京都の人がホームページの、とある情報にアクセスしないといけないとして、その情報にアクセスするのに10秒でアクセスできる分かりやすいデザインと、情報のある位置が予測と全然違ってアクセスに1分かかってしまうデザインがあったとしたら、1人の人間が約19年間生きるくらいの時間コストの差が生まれる。おそろしい損失だ。ホームページのアクセシビリティに関わらず、無駄なコストを削減するために、予測や期待、コンテクストの構成について人々は真剣に考えなければいけないように思う。

 とりとめもなく言葉が散らばってしまったが、読者のハイコンテクストで補完しながら読んでくれることを期待する。

 

鯉よ "鷹未"へ

 気分転換に書籍部を散策していたら、『絶対フォント感を身につける。』というタイトルの本が目に留まった。異様な魅力に惹きつけられ、気が付いたらレジへ足を運んでいた。この本である。

MdN EXTRA Vol. 5 絶対フォント感を身につける。|株式会社エムディエヌコーポレーション

私からは、余計な説明など不要だ。少しでも魅力を感じたなら、一読してみてほしい。フォントに向ける視点を教えてくれる。読み終わった頃には、日常、目の当たりにしている何気ない風景に、一つ奥行きが増えることになるだろう。

  ある分野を学習するとき、その分野をよく知っている人が書いたロードマップがあると、とても助かる。良いロードマップには二種類ある。分かっている人にとってみると必要十分で素晴らしいと感じるが、分からない人には難しいというものと、分からない人にとってみると一歩一歩進むことができた助かるが、分かっている人には冗長だというものだ。良さが異なるからひとくくりにして評価してはいけない。ここでは、よく分かっていない状態を想定しているので、後者の良さを持つロードマップが便利だということだ。

 しかし、いつもそんなロードマップがあるとは限らない。むしろ、ロードマップが整備されているケースはとても少ない。そんなとき、私がやるのが、とりあえず百回試すというものだ。よく分からなくても百回なんとなく繰り返して試していれば、少しは何かが分かるようになる。何が分かっているのかは分からないこともあるが、何か感覚が掴める。これまで、私は、1年でラーメン百杯食べてみたり、1年で本を百冊読んでみたり、アニメを100本見てみたりした(その中でとても良いと感じたものをいくつか挙げると、『ピンポン』『SHIROBAKO』『ばらかもん』『スペース ダンディ』『宇宙よりも遠い場所』『四畳半神話大系』『けものフレンズ』『化物語』『日常』『天元突破グレンラガン』『氷菓』『輪るピングドラム』 といったところか。)。今年は日本酒を100種類飲んでみた。何でもいいからとりあえず100回試してみたり、100時間やってみたりすると、それまでよく分からなかったものに対して、何か差異を見つけられるようになる。

 ただ100回繰り返しているだけでも、何か掴めることがあるが、学習効率が悪い。何が違うかを探っていき、次に活かすということを意識的に行っていった方が効率が良い。統計学的な言葉で表すならば、パターン認識によって、異なるパターン・エラーパターンを把握して、因果推論でその原因を追求し、修正するという作業を愚直に続けていくといったところだろうか。これは、人生のあらゆるものに対する上達のコツだと思われる。このコツが若いうちに身についたかどうかがとても重要だろう。時として、この作業は、精神が磨り減る作業になる。何も見えない暗闇の中で何かを探す作業になったり、自分の誤りを探していく作業になったりするわけで、辛くなることもあるが(楽しくできるということであれば、それは才能なのだと思う。)、これをできるかどうかで、その先にあるものが見えるか否かが決まる。

  上達した者だけが、知っているものだけが眺められる地平というのがある。たとえば、「渋谷のハチ公、上野待ち」というフレーズを聞いて、あぁなるほどと楽しめる人は、渋谷と上野の関係と、ハチ公と上野の関係を知っている人だろう。知らないと何を言ってるか分からないため、分かっている人と地平を共有できない。知っている人だけが感じられる空間構造があって、遠く離れた点と点がつながる感じがとても快感である。それは、秘密の共有のような快感である。これが大っぴらに共有されていることであれば、その快感は薄れてしまう。だから、私はあまり下ネタを言わない。下ネタは人類のほとんどが共有できてしまうから。分かってる人が分かるという世界の共有がやはり楽しい。

 『ピンポン』のドラゴンとペコの試合のシーンが好きだ。あの感覚。共有される高みの世界。私ももっと高いところへ飛んでいきたい。

I'm a fuckup and I'm nuts so she's gone

 カルロス・ゴーン金融商品取引法違反容疑で逮捕されたことが話題となっている。自動車産業というものは、徹底したシステマティックな分業を以てして発展してきた。そのシステムのうちの1つの代表的存在が逮捕された。何が起きているのかは詳細を知らないので、ここでは語らない。

 

 代表が分業において果たす役割は大きい。その役割は、まず指示、統率、鼓舞は自明だろう。もうひとつ代表には重要な役割がある。それは穢れた際の共同体の浄化だ。不祥事を起こした会社の社長などは辞任したり、ときには自殺したりする。ちなみに、伊坂幸太郎の『グラスホッパー』の鯨(人を自殺させるタイプの殺し屋。)は、不祥事を起こした会社だったか政党だったかのエラい人を自殺させる際に、自殺させることの意味についてこんなことを言っている。「大筋では、「これで許してやろうじゃないか」という暗黙の了解のようなものが広がる。生贄を差し出されると、理屈に合わなくても、それ以上責めるのが面倒くさくなる。」

 

 共同体における王権の特質のひとつには日常生活において堆積される脅威や災厄をひきうけ、それを祓う役割を負わされていることがある。王権というものは穢れの浄化装置らしい。災厄が起こった場合、その原因を王に帰し、王を殺害する、'王殺し'っていう習俗が未開の社会にはある。また偽王(モックキング)という制度もある。王権の浄化作用の役割を祝祭の場で王を演じる奴隷や捕虜、すなわち偽の王に肩代わりさせるシステムのこと。ここらへんの話は、今までの記事で何度か出てきた赤坂憲雄の『異人論序説』に書かれている。社長の自殺と王殺しはとても似ている。

 

 自分も代表的な立場を任された経験は何度かあるが、うまくその役割を果たせたと自信を持って言えはしない。指示、統率、鼓舞、浄化(浄化は場面として経験していない。)をやるときは、多くの要素を頭の中に抱えて、当然自分のことをこなしながら、実行していかないといけない。そういう器用な立ち振る舞いがまだできるだけの能力を持っていないのだろう。自分のことに集中して、パフォーマンスを上げることくらいしかできないケツの青い若造なのだ。いい加減、レベルアップしないといけい時期なのだろう。最近、『NARUTO』を読み返していて、キャラクターが成長していくのを見るにつれて、そう思った。

 

(2012年11月11日に書いたものを編集)

心変わりは、人の世の常と申しますから

 ここ半年、今まで属していなかったコミュニティにお邪魔する機会が増えた。増えたというより、半分意識的に、そういう機会を増やしている。当然、最初の腰を上げるのは重いのだけれど、実際に行ってみると、従来の自分の行動パターンからは得られない発想や新しい出会いがあって面白い。いつだったか、ネットワークの研究の話を聞いたとき、多種多様なコミュニティに属している人はそうでない人より年収が高い傾向があるなんてことを聞いたこともある。年収の高い人は別のコミュニティに行けるだけの余裕があるってことなのかもしれない。そんな可能性もあるけれど、別のコミュニティに参加すれば、知らなかった世界が開けたりして、年収のようなものへの作用があるとも考えられる。コミュニティとコミュニティの狭間の人を異人と呼んだりしたと思うのだが、異人の役割といった、このへんの話は赤坂憲雄『異人論序説』に詳しく、面白かった記憶がある。いつも属しているコミュニティにばかりいないで、たまには、外に飛び出してみたりするのは面白いし、それが億劫に感じて、できなくなるような自分には、できることなら、なりたくないものだ。

 新しいコミュニティに行くと感じるのは、コミュニティというものが生き続けているというのはすごいことだということだ。コミュニティのメンバーの各々が、そのコミュニティに対して集まろうという気持ちがなければ、コミュニティは成立しえない。コミュニティを見ていると、積極的にコミュニティを運営しようとしている層と、運営されているコミュニティが生きているなら参加し、協力しようとする層と、参加はするがとくに協力しない層と、離れていく層があると感じる。これらの層がどれくらいの厚みがあって、どれくらいの熱量があるのかがコミュニティの存続・活発度に関わってくると考えられる。各々のメンバーは、それぞれの事情を抱えており、コミュニティへの貢献を一律に強制することは自律的なコミュニティでは難しい。コミュニティのメンバー構成やシステムによっても、メンバーの行動は変わってくる。様々な要因が絡み合っている中で、コミュニティというものが明かりを灯しているのは実はすごいことなんだと最近、実感している。

 コミュニティが存続していることで、属しているメンバーは受ける便益(どういった形かは決まらない。)がある。一方で、コミュニティを存続させるためには貢献が必要で、属しているメンバーにとって、費用(便益同様、どういった形かは決まらない。)となる。ここで、費用を嫌う一方で、便益を受け取るメンバーも、もちろん存在する。人なのだから。コミュニティを運営する人にとって、そういった人への態度というのが難しい。

 個人的に理想として思い描くコミュニティのメンバーのあるべき姿というものがある。それは、余裕があるときは自分が費用を被っても貢献するという姿勢だ。みんなが僅かな自己犠牲を捧げることでコミュニティが成立し、そのコミュニティによって大きな恩恵を得られるというのならばそうすべきだと思う。常に美味しいところだけ持って立ち去ってしまうような姿勢は個人的な理想的見地からすると、望ましくない。自分はそうありたくないし、他人もできることなら、そうあってほしくない。これが、そんな私のエゴである。

ユダヤ人の知恵を借りて資源配分したいときの覚書

 

ユダヤ人の平等な配分の仕方を自動的にやる方法

【用途】
庭から石油が湧いてきたときを想定してほしい。どうやら年間100万トンの産出ができるようだ。兄弟がそれぞれ権利を主張しており、兄は100万トンの権利を持つと主張しており、弟は50万トンの権利を持つと主張している。権利関係を確かめたところ、二人の主張はどうやら正しい。しかし、二人の権利の総量は150万トンで実際に存在する量の100万トンを超えている。このような場面で、どのように石油を配分するのが良いのだろうか。半分ずつに分けるという方法もあるし、割合に応じて2:1に分ける方法もあるが、ユダヤ人の聖典であるところの『タルムード』が規定する分配方法は少し異なる。このケースでは、75万トンと25万トンに分けられるようだ。石油の量が50万トンだと、25万トンずつになり、石油の量が、石油の量が120万トンだと、85万トンと35万トンになる。
この配分方法は一見不思議に見えるが整合性がある。詳しくは「タルムードの破産問題」や「ミシュナの分配」、「布争いの原理」、「仁(nucleolus)」といったキーワードで調べてほしい。
ここでは、その原理に従って、配分量を楽に計算したくなることがある。そんなときのための関数を作成した。

【内容】
JewishAllocという関数を作成した。引数にはtotalとvdemandをとり、totalには分配対象となるものの総量が入り、vdemandにはそれぞれの権利者の正しい権利の量のベクトルが入る。出力として、その権利者の番号とその人に対応する分配量が書かれたデータフレームが出てくる。
パッケージとして、dplyrとmagrittrが読み込まれるが、コードが書きやすいから使用している。使わなくても、該当箇所を書き換えることは難しくはないだろう。

JewishAlloc <- function(total,vdemand){
  #Loading Packages
  library(dplyr)
  library(magrittr)
  #sum of demand
  sdemand <- sum(vdemand)
  #number of people
  n <- length(vdemand)
  #data.frame
  dfdemand <- data.frame(no = 1:n ,
                       D = vdemand,
                       halfD = vdemand/2,
                       A = rep(0,n))
  counter <- 1 #initial counter
  hw <- 0 #initial height of water (metaphor)
  skip <- 0 #0は通常の配分処理を行う。1はdemand通りに配分。2は設定に問題あり。
  dfdemand <- dfdemand %>% arrange(D) #sort by amount
  if(sdemand <= total){
    #If: sdemand > total -> vallocation = vdemand
    dfdemand$A <- dfdemand$D
    skip <- 1
    } else if(0 < total & total < sdemand/2){
      #If: 0 < total <  sdemand/2
      remain <- total #initial remain
      reverse <- 0
      } else if(sdemand/2 <= total & total< sdemand){
        #If: sdemand/2 < total < sdemand
        remain <- sdemand - total #initial remain reverse
        #(空気を水に,水を空気にのイメージ)
        reverse <- 1
        } else{skip <- 2}
  if(skip == 0){
    while((n - counter + 1)*(dfdemand$halfD[counter] - hw) < remain){
      hw <- dfdemand$halfD[counter]
      remain <- remain - hw*(n-counter+1)
      dfdemand$A[counter] <- hw
      counter <- counter + 1
      }
    #dfに逐一入れる。0のとこに最後追加。
    dfdemand$A <- ifelse(dfdemand$A==0, hw + remain/(n- counter + 1), dfdemand$A)
    #reverseが1なら引き算
    if(reverse == 1){
      dfdemand$A <- dfdemand$D - dfdemand$A
    }
    }
  #no でdfをarrangeして元に戻す。
  dfdemand <- dfdemand %>% arrange(no)
  colnames(dfdemand) <- c("no","D","halfD","Alloc")
  if(skip == 2){
    print("something wrong!")
    }else{return(dfdemand[c("no","Alloc")])}
}

イデアのイメージとしては、需要量の多い順に並べて、半分に分けて、上下に貼り付けた筒をつくり、横をくりぬいた箱をつくる。上から水を流してやると、その通りの配分となるイメージだ。hwという変数は水の高さを上げていくイメージ。remainは徐々に水面を上げていってまだ水がどのくらい残っているのかを表している。次の高さまでいけないくらいのremainになったら、等分してやるといった具合だ。reverseという変数は、半分を越したところの計算は対称性を利用してあげると上手くいくので、そのようにしている。空気を水に、水を空気にして計算したあと、対称性を用いて元に戻す感覚だ。(たぶんここのパラグラフは文字だけでは人に伝わりにくいとは思う。)

最初の石油のケースを試してみる。最初の使用ではパッケージの読み込みの出力が出てくる。

t <- 100
vd <- c(100,50)
JewishAlloc(total = t, vdemand = vd)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
##   no Alloc
## 1  1    75
## 2  2    25

二番目のケース。

t <- 50
vd <- c(100,50)
JewishAlloc(total = t, vdemand = vd)
##   no Alloc
## 1  1    25
## 2  2    25

三番目のケース

t <- 120
vd <- c(100,50)
JewishAlloc(total = t, vdemand = vd)
##   no Alloc
## 1  1    85
## 2  2    35

想定通りの出力が出ている。権利の総量に対して十分な量がある場合は、需要量分全てが配分される。変なケースが出るときは、something wrongが出力されるようにした。たとえば、totalが負の値のときは、

t <- -200
vd <- c(100,50)
JewishAlloc(total = t, vdemand = vd)
## [1] "something wrong!"

となる。

権利の主張者が二人より多いときでも配分は出力されるように作成されている。たとえば、四人兄弟で、総量が150、それぞれの主張が100,75,50,25の場合は

t <- 150
vd <- c(100,75,50,25)
JewishAlloc(total = t, vdemand = vd)
##   no Alloc
## 1  1  87.5
## 2  2  62.5
## 3  3  25.0
## 4  4  12.5

となる。

【記憶の検索キーワード】
ユダヤ人, 配分, 知恵, 遺産, 布, タルムード, ミシュナ, 仁(nucleolus), 水を落とすイメージ

壊れるほど愛しても1/3も伝わらない純情な感情との衝動遊戯

 

【ABSTRACT】

一度壊れるほど愛したとき、1/3の感情が伝わるとして、壊れるほど愛する回数を増やしていくときの、すべての感情が伝わっている確率を計算した。感情が複雑になればなるほど、全てを伝えきるのは難しくなるという結論が得られた。

【OBJECTIVE】

SIAM SHADEの曲に『1/3の純情な感情』というものがある。この曲は、こう始まる。

壊れるほど愛しても1/3も伝わらない 純情な愛情は空回り I love you さえ言えないでいるMy heart

では、いったいぜんたい、どのくらい愛せば良いのだろうか。このような疑問が自然と湧いてくる。感情を伝えるのはとても難しいことだというのは周知の通りであるが、感情を全て伝えたいという欲求は否定されるべきではない。ただ、壊れるほど愛した結果、壊してしまってはいけない。そんなわけで、壊れるほど愛する回数を増やしていくとき、感情がどの程度伝わっているのかを考えていく。

【METHODS】

実際に、壊れるほど誰かを愛して、その人にどれくらい感情が伝わったかチェックするという手法が第一に思い浮かぶ。しかし、この手法には問題がいくつかある。壊れるほど愛した結果、その人を壊してしまってはいけないし、どれくらい感情が伝わったかをチェックするのはとても難しい(一番問題なのは壊れるほど愛する誰かの存在なのだが、これはここでは触れずに話を進めることにする。)。

こういう場面で役立つのがモデルだ。現象を近似・抽象化したモデルを作って考える。感情を要素に分解して、壊れるほど愛すると、要素のどれかが確率的に伝わっていくとするモデルをセッティングする。つまり、感情の要素を玉に見立てて、玉を箱に入れて、復元抽出することを想定すると分かりやすい。そのようなモデルで、感情の伝わっている割合、玉で言えば伝わっている玉の種類数の割合を確認していく。

【RESULTS】

感情には3つの要素があってどれか1つが伝わる場合

最も簡単なモデルを作る。伝えたい感情には3つの要素があるとする。1度壊れるほ愛すると、3つの要素のうち1つだけ伝わるとする。その1つの選ばれ方は一様で、それぞれ1/3ずつとする。つまり、ここでは壊れるほど愛すると感情の1/3が伝わるというわけだ。歌詞では1/3も伝わらないとあるが、簡単化のため、1/3とする。非復元抽出としてしまうと、3回愛せば終わってしまうので、復元抽出を考える。
たとえば、A,B,Cの要素があるとして、それぞれ1/3の確率で伝わるとする。5回壊れるほど愛したとして、A,B,A,A,Bと伝わる要素が実現したならば、伝わっているのはAとBで、Cは伝わっていないということになる。
初期値ベクトルと推移行列を用意して積をとれば、n回愛したあとの伝わっている確率は確認できるだろう。行列の積は面倒くさいので、以下、Rを用いて計算していく。

まず、必要なパッケージを読み込む。

library(expm) #行列のべき乗をするためのパッケージ

次に、初期値ベクトルと推移行列を用意する。A,B,Cが伝わっているか否かが問題なので、状態の数は2^3個の8個。伝わっていない状態を0,伝わっている状態を1としたら、(0,0,0),(1,0,0),(0,1,0),(0,0,1),(1,1,0),(1,0,1),(0,1,1),(1,1,1)の8個の状態があり、1回壊れるほど愛すると状態が確率的に推移するので、それを推移行列で表して、計算する。初期値ベクトルは(1,0,0,0,0,0,0,0)の転置したものである。

#初期値ベクトルの作成
vini <- numeric(2^3)
vini[1] <- 1
#推移行列
mtran <- matrix(c(0,1/3,1/3,1/3,0,0,0,0,
                    0,1/3,0,0,1/3,1/3,0,0,
                    0,0,1/3,0,1/3,0,1/3,0,
                    0,0,0,1/3,0,1/3,1/3,0,
                    0,0,0,0,2/3,0,0,1/3,
                    0,0,0,0,0,2/3,0,1/3,
                    0,0,0,0,0,0,2/3,1/3,
                    0,0,0,0,0,0,0,1),
                  nrow = 2^3,byrow = TRUE)

#5回壊れるほど愛したとする
k<-5
pmtran <- mtran%^%k
print(vini%*%pmtran)
##      [,1]        [,2]        [,3]        [,4]      [,5]      [,6]
## [1,]    0 0.004115226 0.004115226 0.004115226 0.1234568 0.1234568
##           [,7]     [,8]
## [1,] 0.1234568 0.617284

これは5回愛した後の(0,0,0),(1,0,0),(0,1,0),(0,0,1),(1,1,0),(1,0,1),(0,1,1),(1,1,1)の状態の確率である。5回壊れるほど愛することができれば、約6割の確率で全ての感情を伝えることができるということが分かる。また3割6分ほどの確率で感情の2/3は伝わっているということになる。

これを関数にする。k回愛した後の状態の確率分布を出力する関数を以下のように作る。

afterk <- function(k){
  vini <- numeric(2^3)
  vini[1] <- 1  #初期値ベクトル
  mtran <- matrix(c(0,1/3,1/3,1/3,0,0,0,0,
                    0,1/3,0,0,1/3,1/3,0,0,
                    0,0,1/3,0,1/3,0,1/3,0,
                    0,0,0,1/3,0,1/3,1/3,0,
                    0,0,0,0,2/3,0,0,1/3,
                    0,0,0,0,0,2/3,0,1/3,
                    0,0,0,0,0,0,2/3,1/3,
                    0,0,0,0,0,0,0,1),
                  nrow = 2^3,byrow = TRUE)    #推移行列
  pmtran <- mtran%^%k
  vini%*%pmtran
}

愛して伝える回数が、1回から15回のケースを計算して、感情が全部伝わっている確率をプロットする。

noftran <- 15
mresult<- apply(matrix(1:noftran, nrow = 1, byrow = TRUE), MARGIN = 2,afterk)
plot(mresult[2^3,], xlab = "伝える回数", ylab = "全部伝わっている確率",type="b")
abline(h=0.95)

y=0.95のところに直線を引いた。11回壊れるほど愛したら、95%以上の確率で全ての感情が伝わっていることが期待できるということだ。こりゃめでたい。

ちなみに、状態を0,1を全ての感情の種類に割り当てたものより、何種類の感情が伝わっているかを表したものの方が、楽に記述できる。結果は変わらない。後の比較のために、y=0.5にも直線を引いた。

afterk <- function(k){
  vini <- numeric(3*1+1)
  vini[1] <- 1  #初期値ベクトル
  mtran <- matrix(c(0,1,0,0,
                    0,1/3,2/3,0,
                    0,0,2/3,1/3,
                    0,0,0,1),
                  nrow = 3+1,byrow = TRUE)    #推移行列
  pmtran <- mtran%^%k
  vini%*%pmtran
}
noftran <- 15
mresult<- apply(matrix(1:noftran, nrow = 1, byrow = TRUE), MARGIN = 2,afterk)
plot(mresult[3+1,], xlab = "伝える回数", ylab = "全部伝わっている確率",type="b")
abline(h=0.95)
abline(h=0.5)

感情には6つの要素があってどれか2つが伝わる場合

感情の要素が3つの場合を考えてきたが、人間の感情はそんなに単純ではない。感情の要素を増やして、感情を複雑にしてみよう。具体的には同じセッティングで感情の要素を6つにして、どれか2つが伝わるとする。同様に関数を作成して、全ての感情が伝わっている確率をプロットする。

afterk <- function(k){
  vini <- numeric(3*2+1)
  vini[1] <- 1  #初期値ベクトル
  mtran <- matrix(c(0,0,choose(6,2),0,0,0,0,
                    0,0,choose(5,1),choose(5,2),0,0,0,
                    0,0,choose(2,2),choose(2,1)*choose(4,1),choose(4,2),0,0,
                    0,0,0,choose(3,2),choose(3,1)*choose(3,1),choose(3,2),0,
                    0,0,0,0,choose(4,2),choose(4,1)*choose(2,1),choose(2,2),
                    0,0,0,0,0,choose(5,2),choose(5,1),
                    0,0,0,0,0,0,choose(6,2)),
                  nrow = 3*2+1,byrow = TRUE)    #推移行列
  mtran <- mtran/choose(6,2)
  pmtran <- mtran%^%k
  vini%*%pmtran
}
noftran <- 15
mresult<- apply(matrix(1:noftran, nrow = 1, byrow = TRUE), MARGIN = 2,afterk)
plot(mresult[3*2+1,], xlab = "伝える回数", ylab = "全部伝わっている確率",type="b")
abline(h=0.95)
abline(h=0.5)

12回壊れるほど愛したら、95%以上の確率で全ての感情が伝わっていることが期待できるということだ。感情が3つのときは11回であったのに比べて必要な回数が増えている。伝える回数の増加に伴う確率の上昇も緩やかになっていることが分かる。これは同じ要素が伝わてしまう確率、つまりダブって伝わる確率が増えているためである。感情の要素をさらに増やしていくと同様のことが確認できる(昔pythonで推移行列を簡単に作成できるコードを書いたのだが、どこかに消えてしまったし、そのアイデアが思い出せないし、すぐに思いつかない。書ける人は書いて確認してほしい。)。このことは、感情が複雑になればなるほど、感情を伝えるのには時間がかかると解釈することができる。

【CONCLUSIONS】

一度壊れるほど愛したとき、1/3の感情が伝わるとして、壊れるほど愛する回数を増やしていくときの、感情の全部が伝わっている確率を計算した結果、感情が複雑になればなるほど、全てを伝えきるのは難しくなるという結論が得られた。

別の応用先としては、ガチャのコンプ問題が考えられる。ガチャの出てくるものが一様の確率で選ばれる復元抽出だった場合、今回のモデルと同様の問題に帰着する。また、以下のような拡張系も予想できる。

伝わる確率が一様だと想定しているが、そうでないケースも考えられる。分布を変えるとどうなるかは今回は試していない。伝わりにくい感情だってあるだろう。また、伝わる確率がそれぞれ独立だということを仮定していたが、あることが伝わっている状態ならば、別のあることは伝わりやすいということや、その逆もありうる。伝えたと思った感情の要素は次は少し弱めにして他の要素が伝わるように工夫することだって考えられる。そういった相関関係や連鎖関係を仮定したモデリングも今回は作っていない。壊れるほど愛することができる関係ならば、相手からのシグナルを受け取ったり、反応を見てみたりしながら、どれが伝わっているかを確認したり、推測したりすることもできるだろう。そんなモデルも考えられる。

今回モデル化したのは、n回伝えた時点での伝わり具合であったが、視点を変えた問題として、全部伝わるまでに何回かかるのかを確率的に考えることができるだろう。おそらく、負の二項分布の拡張になるのだろうと予想しているが、実際にどのような分布になるかは考えていない。

一度壊れるほど愛した場合、壊れるリスクについての検討もしていない。今回は何度壊れるほど愛しても壊れない仮定を置いていた。壊れるリスクを付与したモデルを作っても面白いのかもしれない。

以上挙げたような、拡張可能性を有したモデルであるので、好きに拡張して、壊れるほど愛する際の参考にしてください。

【REFERENCES】

SIAM SHADE1/3の純情な感情
今回の発想の源泉となった曲。聞いたことのない方はぜひ一度聞いてみてください。