Atsumaru Engineer's Blog

集客プラットフォーム事業を手がける株式会社あつまるのエンジニアブログです

Goodpatch × Atsumaruで合同勉強会を開催しました!

「マネジメントをどう機能させるか」は、組織運営において永遠のテーマ。
今回は「マネジメント交流会」と題し、Goodpatch様のマネジメント層の方々をお招きして、合同で勉強会を開催しました!
両社のマネジメント層が集まり、ナレッジを共有したり、ディスカッションしたりと大いに白熱、、、
その勉強会の様子を、一部だけご紹介します!

【目次】

第1部:テーマ別LT会!

①歴史を紐解く組織年表
②中途採用どうやってる?
③評価基準と評価プロセス
④品質管理について

上記のテーマについて両社から1名ずつ選出して発表し、最後に質疑応答を行いました。

▼Goodpatch様 f:id:snoopy_no_sora:20200916133007p:plain

▼あつまる f:id:snoopy_no_sora:20200916132836p:plain

本記事では、私が特に印象的だったGoodpatch山木様の発表について書きたいと思います。

Goodpatch|山木様「評価基準と評価プロセス」

Goodpatch山木様は、Goodpatchではどのような評価基準を置き、どのような評価プロセスを経ているかという点について、発表されました。

▼Goodpatch山木様 f:id:snoopy_no_sora:20200916134756j:plain

Goodpatchが評価において焦点を当てていらっしゃるのは、下記4項目。

  • 等級要件 例:品質マネジメントができるか
  • NPS(顧客推奨度) 例:自社の他部署にGoodpatchを推薦したいか
  • OKR(目標達成度) 例:案件のナレッジシェア×10
  • 組織貢献 例:Goodpatch Blogへの記事投稿

これらの4つを3ヶ月に1回中間評価を実施し、マネジメント層が自己評価をフィードバック。 さらに3ヶ月後の本評価の際に、改めて自己評価をフィードバックをされるとのこと。 その上で、毎週30分はメンバーとの1on1を実施して、自己評価とフィードバックのズレをできるだけ小さくなるようにされているそうです。

物凄い徹底ぶり、、、

特に印象的だったのは、発表の最後にあった「メンバーとのコミュニケーションストロークを多く心がけて、定量・定性の両観点から納得感がある評価を出せることを心がけている」という言葉。
私自身、デザイナーやエンジニアのより良い評価方法を模索しており、課題に感じていました。
今回の山木様の発表を聞いて、さっそく自チームに取り入れたいことが山ほどできました!

第2部:懇親会!

お酒を飲みながら、お互いに質問をぶつけ合い、熱い議論が展開されました。
大いに盛り上がったのが、

「あなたにとってデザインとは何か?」
「良いデザイナー、良いエンジニアの定義は?」
という質問。
シンプルな問いだけに、その人の内面や考え方も反映される哲学的な質問、、、。
両社のデザイナー・エンジニアから、様々な答えがありました。

「デザインは、クライアントの想いを伝えるための手段」
「デザインは『いたづら』。相手からリアクションを引き出す思考がデザインと似ている」
「デザインは、『伝える』ものではなく、『伝わる』ものだ」
「良いデザイナーとは、問題設定と問題解決ができる人だ」
「良いエンジニアとは、経済価値にコミットできるエンジニアだ」
etc...

クライアント企業に感動を与えるために、デザイナーとして、エンジニアとして、いかにプロジェクトに臨むべきか、大いに学びになりました。

▼熱い議論の様子
f:id:snoopy_no_sora:20200916134431j:plain

最後に

Atsumaruでは、今後もデザイナー/エンジニア同士がナレッジを共有できる場を創っていきたいと考えています。
合同開催のお問い合わせは、ぜひこちらからご連絡ください!
Goodpatch様のブログ「Goodpatch Blog」もぜひご覧ください!

論文を読もう

 

初投稿です!

株式会社あつまるでエンジニアをやってます!

円城寺健といいます!

 

私事ですが、初投稿なのでお題目決めには悩まされました。。。

新卒1年目として、入社4ヶ月目の感想でも書こうか?それともエンジニアらしく、テクノロジーについてつらつら書いていこうか? etc...

 

悩んだ結果、「論文を読もう」

 

なんのこっちゃって感じですよね(笑)

自分でもそう思います(笑)

 

でも、書きたいので書きます!お時間ある方は是非お付き合いください!(_ _ )

 

 

今回のブログで伝えたいことは2つ!

・論文って、ちゃんと仮説・検証して世の中に提示されてるものだから、結構信頼できるんだよ!

・論文って、実は簡単に見ることができるんだよ!しかも無料で!

では、つらつらと書いていきますね(笑)

 

 

<閑話休題>

 

 

皆さんは普段論文を読んでいますか??

  私はたまに読んでいます。大学の卒業研究の為に論文を読み始めてから、たまに読むようになりました。

  最近読んだ論文のリンクを貼っておくので、是非見てみてください!!

(好んで聴いている音楽で、うつ傾向との関連を調べた論文です!!読んでて面白かったです!!)

聴き手の精神的健康状態と音楽の嗜好性の関連

https://www.jstage.jst.go.jp/article/jjpm/57/2/57_160/_article/-char/ja/

 

 

話は戻って、「そもそも論文って何??単語としては知ってる」って人が多いのではと思います。 ですので、Wikipedia 先生に聞いてみましょう。

論文(ろんぶん、英: paper)とは、学問の研究成果などのあるテーマについて論理的な手法で書き記した文章。 漢文中の語句としては“文ヲ論ズ”=“文学について論ずる”の意味でも使われた。また、特定の研究成果についての記述ではなく、あるテーマについて論述する論文の一つの形式として小論文がある。

 

出典:フリー百科事典『ウィキペディア(Wikipedia) https://ja.wikipedia.org/wiki/%E8%AB%96%E6%96%87

とりあえず今は、「何か良く分かんないけど、お堅い読み物なんだな」みたいイメージで大丈夫です!!

 

【 論文って、ちゃんと仮説・検証して世の中に提示されてるものだから、結構信頼できるんだよ! 】

 

「本当かよ」と思いの方、本当です(笑)

重要なのは「仮説・検証」「世の中に提示」の部分です。

 

まずは「仮説」についてです!仮説は下記の論文体裁の中の「序論」と「本論(前半)」で出てきます!

論文は次のようなIMRAD型の構成を取ることが多い。

 

 題名

 要約(本文の内容を要約した文章)

 序論(背景、研究の動機や意義、成果の位置づけ、重要性など)

 準備(論文を読むための既存の基礎知識など)

 本論(理論、実験、調査の過程及び得られた結果など)

 結論(本論で得られたデータの叙述的な説明)

 参考文献

 執筆に当たって協力を得た人々・機関への謝辞

 付録(証明や実験の詳細など)

 

出典:フリー百科事典『ウィキペディア(Wikipedia) https://ja.wikipedia.org/wiki/%E8%AB%96%E6%96%87

「序論」での仮説は、ちょっと感覚よりです。「昔こんな研究があって、この研究を応用したらもっと凄い事が証明できるのでは」みたいな感じ。 殆どの論文は、「○○をすると□□という結果になるのでは。しかもこれ、科学の発展に繋がるかも!!よしやってみよう!!」みたいな動機が序論で記述されています。

 

「本論(前半)」では、序論での仮説を具体的に学術的な(化学的な)レベルに落とし込んでいきます。「まずは○○をします。次に××をします。すると、□□という結果が得られるはずです。」みたいな感じ。 ここでは、既に証明されている、信用できる法則やデータを用いて理論を組み立てていることが殆どです。ですので、本論(準備)で一気に信頼性が上がります。

 

次に「検証」についてです!検証は前述の論文体裁の「本論(後半)」と「結論」で出てきます!

 

「本論(後半)」では、「組み立てた理論を実際にやってみました!」みたいなことが書かれています。よく分からない機械使って人集めてやってるものから、大人数にアンケート回答してもらったものまで、その時々で最適な方法で「データを取っています」(ここめっちゃ重要!!)。

 

「結論」では、「本論(後半)で取ったデータを詳しく見ていったら、こういう法則や可能性がありました!!」みたいなことが書かれています。「本論(後半)」で取ったデータを「既に証明されている法則や数式」に当て嵌めて見えてくる、気付きや発見が書かれています。

 

最後に「世の中に提示」についてです。論文は「査読制度」というものによって、より説得力のあるものになります。

査読制度とは、著者にはその名前を伏せておく査読者(レフェリー)によって論文の内容について審査を行い、掲載(アクセプト)、修正後に掲載、再査読、掲載拒否(リジェクト)などの判定を行うものである。何度かの修正を経て学術雑誌に掲載される場合は、初版の投稿から掲載まで数か月から数年を要することが多い。

 

出典:フリー百科事典『ウィキペディア(Wikipedia) https://ja.wikipedia.org/wiki/%E8%AB%96%E6%96%87

この査読制度、かかる時はめちゃくちゃ年月がかかります。 最近証明された、京都大学の望月新一教授の abc予想は、初版から投稿までに8年もかかっています!! 既存の方法ではなく、望月教授が新たに開発した「宇宙際タイヒミュラー理論」というものが研究で使われていた為、しっかりと内容を理解して審査するのに長い時間がかかったのです。

 

研究者・科学者は自分の知らない理論だからといって適当な評価はしません。理論を理解して、過去の研究データなどと比較しながら、査読を行い、GOサインを出すのです。 つまり、世の中に出回っている論文は、「多くの研究者・科学者に太鼓判を押されたもの」なんです!!

 

論文は、「仮説」と「検証」がしっかりしていて、なおかつ、多くの研究者・科学者から太鼓判を押されているから、信憑性のあるものになっているのです!!

 

以上から、論文は、適当に google 検索して出てきたブログよりもはるかに信頼できるものなんです!!

 

但し!!!「論文に記述されていることは全て正しい」とは思わないでください!!! 「世の中、絶対に正しいものなんて存在しない」というスタンスは持ってください!!

 

論文はあくまでも「個人のブログよりは信頼性が高い情報源」であることを念頭においてください!!(それでも、適当にヒットしたブログより遥かに信用できます)

 

【 論文って、実は簡単に見ることができるんだよ!しかも無料で! 】

 

論文は、実は google 検索すれば出てきます!!多くの場合は下記サイトがヒットすると思います。

CiNii Articles
https://ci.nii.ac.jp/
J-STAGE
https://www.jstage.jst.go.jp/browse/-char/ja/
Google Scholar
https://scholar.google.co.jp/

基本的に Google Scholar で事足ります(日本語対応ありがとう google さん)。 適当なワードで検索しても何かしらの論文がヒットします。便利です(本当に)。

 

試しに、「ヨガ」について検索してみます(最近、週一でヨガをしています。ヨガ、めちゃくちゃ良いです)

 

f:id:Prq8EHGiTndTH3W:20200719132246p:plain
トップにヨガを入力

 

f:id:Prq8EHGiTndTH3W:20200719132305p:plain
検索候補がいくつか出てきた!!「ヨガ効果」を選んでみよう!!

 

f:id:Prq8EHGiTndTH3W:20200719132321p:plain
なんか出てきた!!(笑) とりあえず、上から3番目の「ヨガの心理的効果についての調査研究」をクリックしてみよう!

 

f:id:Prq8EHGiTndTH3W:20200719132311p:plain
なんだこのページは(笑) PDFあるから見てみようかな〜(適当なノリで)

 

f:id:Prq8EHGiTndTH3W:20200720074823p:plain
なんか。。。出てきた。。。

 

はい〜論文を見ることができました!普通に google 検索するのとあまり変わません!論文ってこんなに簡単に見ることができるとは!!(笑)

 

皆さんも、これを機に、論文デビューをしてみてください!!

 

参考

フリー百科事典『ウィキペディア(Wikipedia)

https://ja.wikipedia.org/wiki/%E8%AB%96%E6%96%87

確かな情報は確かな情報源から!論文・書籍検索サイト10選

確かな情報は確かな情報源から!論文・書籍検索サイト10選|ferret

ヨガの心理的効果についての調査研究

https://www.jstage.jst.go.jp/article/cou/44/2/44_110/_article/-char/ja/

 

【統計学】MCMC サンプリングを JavaScript によるアニメーションで実装しながら理解する

Summary

JavaScript(TypeScript) で MCMC ・メトロポリス・ヘイスティング法を実装して解説してみる記事です。
概ね こちらの記事 の JavaScript 実装版です。

この節の内容を実感するために一番良い方法は、どんな計算機言語でもいいから、
ここで述べたことを白紙から実装してみることである。

という訳で実際にやってみました。
手元でアニメーションで動いてくれるものが出来て理解が深まりました 😉👌

作ったもの

まずは成果物をご覧ください。

todays-mitsui.github.io

最初の50回を Burn-in 期間として、棄却含め250回までのサンプリングを散布図にプロットしています。

https://user-images.githubusercontent.com/3040456/85984106-a3072e80-ba23-11ea-8a0d-ec9ead17c1bb.gif
成果物 動作イメージ

薄い灰色でプロットされているのは Burn-in 期間です。受容されたサンプルは青い丸印で、棄却されたサンプルは赤いバツ印でプロットしています。
画面の下半分には、受容されたサンプルだけ使ってトレースラインとヒストグラムを描画しています。

しばらく放置して棄却含め2000回までサンプリングしたらこんな感じになります。

f:id:todays_mitsui:20200630110311p:plain
棄却含め2000回までのサンプリング結果

本記事では実装のコードを見ながら若干の解説を加えます。

ちなみに、サンプルしたデータの表示のために Vue.js と Chart.js を使いましたが、サンプリングそのもののロジックはライブラリを使わずに(Vanilla JS で)書いています。

目標分布 (Target Distribution)

\displaystyle \begin{eqnarray}f(x,y) &=& \sqrt{1-b^{2} \over 2 \pi} \exp{(-{1 \over 2} (x^{2} - 2bxy + y^{2}))} \\\ 
&\propto& \exp{(-{1 \over 2} (x^{2} - 2bxy + y^{2}))} \end{eqnarray}

本家に倣って 2次元正規分布から正規化定数を除いたものを使います。

実際にコードに組み込むのは \exp{(-{1 \over 2} (x^{2} - 2bxy + y^{2}))} の式になります。この関数は全区間で積分したときに結果が 1 になりません。その意味でこの関数は **確率密度関数ではありません** 。このような目標とする確率分布に比例する関数を **目標分布のカーネル** と呼びます。
目標分布のカーネルさえ知っていれば、目標分布に従う乱数を生成できるのが MCMC の強みです。

目標分布のカーネルを App.vue の中で p という関数として定義してあります。

/** 目標分布のカーネル */
p ({ x, y }: Point): number {
  return Math.exp(-0.5 * (x * x - 2 * RHO * x * y + y * y))
}

~

ご覧の通り、 \exp{(-{1 \over 2} (x^{2} - 2bxy + y^{2}))} を愚直に JavaScript で書き下しただけです。

提案分布 (Proposal Distribution)

次に提案分布です。提案分布は 詳細釣り合い条件(Detailed Balance) *1を満たせるものなら自由に選べますが、こちらも本家に倣って下記のようにしました。

/** 提案分布 */
q ({ x, y }: Point): Point {
  return {
    x: x + rnorm(0, SIGMA),
    y: y + rnorm(0, SIGMA)
  }
}

~

ここで rnorm () は正規分布です。今回は Box-Muller法 で実装しました。*2

/**
 * @param m 平均
 * @param s 標準偏差
 */
rnorm (m = 0, s = 1) {
  const rnorm = Math.sqrt(-2 * Math.log(1 - Math.random())) * Math.cos(2 * Math.PI * Math.random())
  return (rnorm + m) * s * s
}

実装の詳細はともかく q() は直前の点 ( x, y ) を引数に与えると次の点の候補 x_{next}, y_{next} を選んで返す関数になっています。
また、「自由に選べる」と書きましたが、直前の点 ( x, y ) を中心として点対称な分布を選ぶと後々の実装がシンプルになるので便利です。今回は点対称な分布になっています。

もちろん提案分布が選んだ候補がすべて受容されるわけではありません。とあるロジックに従って次の点の候補を受容したり棄却したりします。
すべて受容されたら目標分布からのサンプリングにならないですからね。

では具体的にどのようなロジックで候補点の 受容/棄却 を決定するのでしょうか。続いて本題となるサンプリング部分の実装を見てみましょう。

サンプリング

/** サンプル取得処理 */
sample (): Sample {
  // 点 current 、初回は current === undefined なので { x0, y0 } を使う
  const current = this.current || { x: this.x0, y: this.y0 }
  const next = this.q(current)      // 提案分布を使って点 next を選ぶ

  const pCurrent = this.p(current)  // 点 current における目標分布の確率密度
  const pNext = this.p(next)        // 点 next における目標分布の確率密度

  const r = pNext / pCurrent        // 受容確率

  // r が 1 以上ならそのまま受容する (accepted === true になる)
  // r が 1 より小さいなら、確率 r で受容する
  const accepted = r >= 1 || r > uniform(0, 1)

  return {
    count: this.count,
    burnin: this.count < BURN_IN_PERIOD,
    current,
    next,
    result: accepted ? 'accepted' : 'rejected'
  }
}

~

流れを追ってみましょう。

まずは次の点を選ぶために点 current を変数に代入しておきます。

  // 点 current 、初回は current === undefined なので { x0, y0 } を使う
  const current = this.current || { x: this.x0, y: this.y0 }

ただし、初回のサンプリング時には current はありません。current の初期値は目標分布に合わせて適当に選びます。

...とはいえ多変量の確率分布の解析をするときは目標分布の大まかな形すら分からないことが多く、初期値を適当に選ぶのも容易ではありません。
ではどうするかと言うと、本当に何でもいいので適当に選びます。今回はユーザーが自由に初期値を設定できるような UI にしてみました。

f:id:todays_mitsui:20200630120641p:plain

 

提案分布 q() を使って次の点の候補になる next を取得します。

  const next = this.q(current)      // 提案分布を使って点 next を選ぶ

 

current, next を目標分布 p() に渡して、それぞれの点における確率密度を計算します。

  const pCurrent = this.p(current)  // 点 current における目標分布の確率密度
  const pNext = this.p(next)        // 点 next における目標分布の確率密度

pCurrent, pNext は確率密度なので必ず 0 以上の実数になります。とはいえ **確率ではない** ので 1 以下になるとは限りません。

 

続いて pNextpCurrent で割ったとある変数 r を定義します。

  const r = pNext / pCurrent        // 受容確率

r は確率密度同士の比ですが、こちらも **確率ではない** ので 1 以下になるとは限りません。
この r を基準にして点 next を受容したり棄却したりします。具体的には、

  • r \geqq 1 ならば確率 1 で点 next を受容します。
  • r < 1 ならば確率 r で点 next を受容します。

このようなロジックを採用すると詳細釣り合い条件を満たします。
r は実質的に受容確率と呼べる値になっていますね。

 

という訳で r を使って next を受容するか棄却するかを決めます。

  // r が 1 以上ならそのまま受容する (accepted === true になる)
  // r が 1 より小さいなら、確率 r で受容する
  const accepted = r >= 1 || r > uniform(0, 1)

関数 uniform() は0以上1未満の一様分布から乱数を生成します。実質的に Math.random() と同等です。

 

最後に生成した諸々の値をまとめて return します。

  return {
    count: this.count,
    burnin: this.count < BURN_IN_PERIOD,
    current,
    next,
    result: accepted ? 'accepted' : 'rejected'
  }

count は「何回目に生成されたサンプルなのか」を表現しています。burnin はサンプルが Burn-in 期間のものかを真理値で保持しています。

 

ここで見てきた関数 sample() はただ一度のサンプリングをする関数です。もちろん多数のサンプルを取得して目標分布の特徴を掴みたいわけなので sample() は繰り返し呼び出されます。

サンプリングループ

/** サンプル取得を繰り返す実行するためのループ */
loop () {
  // サンプル取得
  const sample = this.sample()

  // 取得した sample が受容されていた場合は、次に備えて点 current を点 next で置き換える
  if (sample.result === 'accepted') { this.current = sample.next }

  this.samples.push(sample)
  this.count += 1

  // 1000 / speed ミリ秒だけ待ってから loop() を再び呼び出す
  if (!this.pause) { setTimeout(this.loop, 1000 / this.speed) }
}

~

メトロポリス・ヘイスティング法の本質は sample() 関数の中で解説しきっているので、loop() の実装は短いです。

 

まずは先ほどの sample() を呼び出してサンプルを取得します。

  // サンプル取得
  const sample = this.sample()

 

取得したサンプルが受容されていれば currentsample.next で置き換えます。
逆に、サンプルが棄却されているなら何もしません。点 current は同じ値のまま、次の周回でリトライするということです。

  // 取得した sample が受容されていた場合は、次に備えて点 current を点 next で置き換える
  if (sample.result === 'accepted') { this.current = sample.next }

 

取得した samplesamples 変数にプッシュし、count 変数をインクリメントします。
本来であれば棄却されたサンプルは samples にプッシュせずに捨ててしまっていいのですが、散布図の表示に使ったり受容率の計算に使うこともできるので、今回は 受容/棄却 に依らず全件を samples に保持します。

  this.samples.push(sample)
  this.count += 1

 

最後の1行はサンプリングのスピードを調整したり、サンプリングを一時停止できるようにするためのものです。メトロポリス・ヘイスティング法のロジックとは全く関係ありません。
ともかく loop() の中で loop() を再帰的に呼び出すことでループを実現しています。

  // 1000 / speed ミリ秒だけ待ってから loop() を再び呼び出す
  if (!this.pause) { setTimeout(this.loop, 1000 / this.speed) }

実際に見てみる

ここまでの説明でいまいちピンと来なかった方も、実際に動いているアニメーションを見ればイメージが掴めるかも知れません。
下記に実際に動くページがあります。スピードの設定を 1 にしてゆっくりと動かしてみることをおすすめします。(宣伝)

 

一連のコードは JavaScript(TypeScript) で書かれていてサーバー無しでも動くので、GitHub からクローンして手元で動かしたり、適当に改変したりすると理解が深まると思いますよ。(宣伝)

github.com

 

私からは以上です。

補足: 提案分布の形と受容確率 r について

提案分布の項で、

提案分布は 詳細釣り合い条件(Detailed Balance) を満たせるものなら自由に選べますが、
(...中略...)
また、「自由に選べる」と書きましたが、直前の点 (x,y) を中心として点対称な分布を選ぶと後々の実装がシンプルになるので便利です。

と書きました。
さらっと流しましたが重要なので補足しておきます。

MCMC の教科書を読むと、詳細釣り合い条件を満たすために受容確率*3 r は下記のような値でなければいけないと書かれています。

\displaystyle 元の点\ p\ から次の候補点\ p_{next}\ が選ばれたとき、 \\\
r = \frac{(p_{next}\ から\ p\ が選ばれる確率)(p_{next}\ における目標分布の確率密度)}{(p\ から\ p_{next}\ が選ばれる確率)(p\ における目標分布の確率密度)}

ところがコードの中では

  const pCurrent = this.p(current)  // 点 current における目標分布の確率密度
  const pNext = this.p(next)        // 点 next における目標分布の確率密度
  const r = pNext / pCurrent        // 受容確率

となっています。これは上記を忠実に実装したものではありません。

今回は下記のように元の点 $p$ を中心に点対称な確率分布を提案分布として採用しました。

/** 提案分布 */
q ({ x, y }: Point): Point {
  return {
    x: x + rnorm(0, SIGMA),
    y: y + rnorm(0, SIGMA)
  }
}

点対称な分布を採用することにより、常に (p_{next}\ から\ p\ が選ばれる確率) = (p\ から\ p_{next}\ が選ばれる確率) が成り立ちます。
そのため r の式中の (p_{next}\ から\ p\ が選ばれる確率)/(p\ から\ p_{next}\ が選ばれる確率)1 となり、計算上考えなくてよくなります。

これが「点対称な分布を選ぶと後々の実装がシンプルになるので便利」と書いた理由です。

 

逆に、点対称でない分布を提案分布とすることも可能ですが、上記のとおり詳細釣り合い条件を満たすように厳密に r を計算しないといけないので面倒です。

 

提案分布として正規分布を使う他、適当な実数 a を使って範囲が [x - a, x + a] の一様分布を提案分布にしても同様に点対称な提案分布が作れるでしょう。
その場合、提案分布によって [x - a, x + a] の点が選ばれることはありませんが、そのことはメトロポリス・ヘイスティング法において本質的な問題ではありません。

ただし、a をあまり近くしすぎるとサンプル列の前後の項の相関が大きくなりすぎるため、適当な実数 a をどのように選定するか悩ましいところです。
同様の問題は提案分布として分散の小さな正規分布を使ったときにも起こります。

(とはいえ、一連のサンプリングによって得られたサンプル列を適当にシャッフルしてしまえば前後の項の相関は消えるので、あまり深く考えなくてもいいのかも。※サンプルサイズを充分に大きくする前提なら)

参考記事・参考書籍

スペシャルサンクス

qiita.com
同じ例が Python 実装で解説してあります。この記事を JavsScript(TypeScript) で書き起こしたのが本記事です

 

ベイズの気持ち・MCMC のうれしさを理解するのに最良の入門書。所謂、緑本。ただし、メトロポリス・ヘイスティング法の実装については書かれていない

 

読みやすく数式を添えて正確&網羅的に解説が加えてあるので、この本を理解すればメトロポリス・ヘイスティング法やハミルトニアンモンテカルロ法を実装に落とすことは可能だと思います
この記事を書くために4往復くらい読んでやっと理解したけど...

 

*1:サンプル列が目標分布に収束するために満たすべき各サンプル間の条件。すべてのサンプル間で満たさなければいけない条件なので、もちろん提案分布が選ぶ前後のサンプルについても詳細釣り合い条件を満たさせるように注意しなければいけない。

*2:参考: Javascriptで正規分布の実装まとめ(乱数、累積分布関数など)

*3:ここでの r は1を超えることがあるので実際には「確率」ではありません。教科書によっては「遷移核の補正係数」というような呼び方をしていますが、「遷移核」「補正」という用語を避けて説明を簡単にするために、r を「確率のようなもの」として扱っています。

Sansan API + AWSで企業情報のマスターDBを構築する

こんにちは!エンジニアの金子(@kanekenl)です。
好きな食べ物はポテトサラダです。キングダムの好きな武将は、「麃公(ヒョウコウ)将軍」です。
自己紹介は以上にして、早速内容に入っていきます!😊

※この記事は、具体的な技術というより、ビジネス課題解決のための設計に内容をフォーカスしています!
この記事の技術分野をもっと知りたいよ!という方はTwitterでメンション飛ばしていただけたらと思います!

1. 経緯

社内には数多くのシステムがあります。CRM、ERP、経費精算、、、etc...
そして、その各システムには、企業を登録するUIがあり、それぞれのシステムに企業登録を行います。
そこで課題に上がってくることが以下の2点!

社内の課題😱

①それぞれのツールに何度も同じような情報を入力しなければならない。
※CRMやERPなど各システムに企業名や担当者など共通する情報を何度も入力。。。

②色々な人が入力するので、同じ企業の登録でも表記ゆれをする。
※「株式会社あつまる」「株式会社ATSUMARU」、「(株)あつまる」、「あつまる」、半角や全角、など考え出したらキリがないレベルで表記ゆれがあります。一番の絶叫は、半角カタカナですね。🥶

特に、②に関しては、今後、各システム同士を連携する際にもかなりネックになってきますね。🤔

※イメージ図
f:id:kanekok13:20200517122431p:plain

2. 実現したいこと

①一つのUIに企業を登録すると全てのシステムに同じ企業情報が登録される

②企業情報に関しては、ユーザーに入力させるのではなく、クラウド名刺管理Sansanから企業データを引っ張ってきて、選択させる方式で企業を登録


【流れ】
名刺を写真にとり、Sansanに登録 → システムに企業登録する際は企業一覧が表示されるので選択するだけ
企業名だけではなく、名刺に含まれる企業情報も同時にデータベースに登録されます。

f:id:kanekok13:20200517122323p:plain

2-1. Sansan APIについて

クラウド名刺管理Sansanを契約している企業向けにAPIが公開されています。
APIドキュメント自体は一般公開されています。 非常にわかりやすく、そして、APIリクエストからのレスポンスも早い!!! 色々なパラメータで条件を絞れたり、あらゆる角度から欲しい情報が引っ張れるので、 社内のシステム連携には非常にやりやすく、とても嬉しい!😂

Sansan Open API

2-2. アーキテクト

f:id:kanekok13:20200518101223p:plain

3. 開発のポイント

  • Sansan APIは名刺 Set 取得(期間指定)で12時間前から現在時刻までの取得、Lambdaの実行は30分ごと。
  • LambdaからDynamoDBに企業登録する際は、一度、企業検索をかけて、ないことを確認して、登録している。既に登録されている企業データに関しては、登録処理を行わない。

3-1. 企業入力に関して

名刺登録されている膨大な選択肢から企業を探すのは、非常に困難なため、企業名の入力サジェストで選択できる形にしています。

vue-multiselect.js.org

f:id:kanekok13:20200518113725g:plain:w320:h300

4. 今後の展望

社内システムとの連携に関して、システムA、システムB、システムCと書いていますが、まだ実は連携ができていません。そこで、以下の2点を実現できる基盤と仕組みを創っていきたいと思っています。

  1. 正しい情報の整理
  2. データ登録業務の効率化

あつまるのエンジニア募集

あつまるではエンジニアを募集しています! 最先端のマーケティングプラットフォームを一緒に開発していきましょう!

あと、最近実は、、、あつまるが原宿にオフィス移転しました!!!!

▼内装もかなりこだわっています🤩▼ f:id:kanekok13:20200518103210j:plain f:id:kanekok13:20200518103812j:plain

▼21階の見晴らしも良いです!(東京タワー🗼もスカイツリーも富士山🗻も見えます!)▼ f:id:kanekok13:20200518103634j:plain f:id:kanekok13:20200518103644j:plain

募集記事もぜひ見てください〜!

▼フロントエンドエンジニア▼

www.wantedly.com

▼サーバーサイドエンジニア▼

www.wantedly.com

▼インフラサイドエンジニア▼

www.wantedly.com

あつまるでは、エンジニアイベントに関しても計画中です!
もし、イベントでも、会社でも、オフィスでも、技術的なところでも興味あれば、@kanekenlに気軽に声かけてください!😆
※「僕は王騎将軍が好きです。」というメンションもお待ちしてます。

ブログを読んでいただきありがとうございます!
今後も、定期的にアウトプットしていこうと思います!🤗

確率論的に円周率πを推定してみた

久しぶりの投稿です。
Atsumaruエンジニアの渡邊です。

最近は新規プロジェクトの立ち上げ・ドライブが増えて、なかなかコードを触れていない日々が続いています><

今回は、円周率の求め方で面白いアプローチがあることを知ったので、自分でもやってみた話を書いてみようと思います。

考え方

xy座標を思い浮かべてください。

f:id:snoopy_no_sora:20200226141704p:plain

ここに、原点Oを中心とする、半径rの円(Cとします)と、一辺が2rの正方形(Sとします)を描きます。

f:id:snoopy_no_sora:20200226141708p:plain

Sの中に、ひたすらランダムで点(dot)を打ち続けます。

f:id:snoopy_no_sora:20200226141924p:plain

Sの中を埋め尽くすほど点を打ったとき、「Sの中にある点の数:Cの中にある点の数 ≒ Sの面積:Cの面積」と言えます。

f:id:snoopy_no_sora:20200226141637p:plain

Sの中にある点の数を「s_dot_num」、Cの中にある点の数を「c_dot_num」とおくと、

(c_dot_num) / (s_dot_num)
 = Cの面積 / Sの面積
 = (π * rの2乗) / (2r)の2乗
 = π / 4

となることから、

π = 4 * (c_dot_num) / (s_dot_num)

と定義ができました。
あとは、c_dot_numとs_dot_numをそれぞれ求めることができれば、πの値を推定できます。
(rの値は関係ないようですね)

コード

今回はpythonで書きました。

# 一辺の長さが1の正方形内にランダムにドットを打ち、円周率を推定する。
import random

def estimate_pi(n):
    c_dot_num = 0
    s_dot_num = 0
    for _ in range(n):
        x = random.uniform(0, 1)
        y = random.uniform(0, 1)
        distance = x**2 + y**2
        if distance <= 1:
            c_dot_num += 1
        s_dot_num += 1
    pi = 4 * c_dot_num / s_dot_num
    return pi

if __name__ == '__main__':
    print('dotが100個のとき、円周率は{}'.format(estimate_pi(100)))
    print('dotが1000個のとき、円周率は{}'.format(estimate_pi(1000)))
    print('dotが10000個のとき、円周率は{}'.format(estimate_pi(10000)))
    print('dotが100000個のとき、円周率は{}'.format(estimate_pi(100000)))

※イメージ
f:id:snoopy_no_sora:20200226141715p:plain

実行結果

1回目
f:id:snoopy_no_sora:20200226141655p:plain

2回目
f:id:snoopy_no_sora:20200226141657p:plain

3回目
f:id:snoopy_no_sora:20200226141701p:plain

だいたい3.141前後になりました。

まとめ

今回は確率論的に円周率を求めてみました。
確率論なので、一概に「点の数を多くすれば、より正確な値を求めることができる」というわけでもなさそうです。

いわゆる「統計」や「データ分析」にはいろんなアプローチ・アルゴリズムがあり、新しい何かを知ると「そういうアプローチがあるのか!」とテンション上がります。

幅を広げていきたいな。
(´-`).。oO