2020年12月5日土曜日

Apple Silicon MacBook Air

MacBook Air2013からApple Silicon MacBook Airのときにやったこと

移行アシスタントでやるとすぐに同じ状態で使えるのはいいんだが、要らなそうなファイルも持ってきてしまう。きれいさっぱりな状態にしたかったのでひとまず
  1. まっさらな状態で環境設定
  2. ファイル共有で必要なファイルだけコピペ
  3. 隠しファイルの表示はcommand+shift+.(dot)

ミュージック

  1. ミュージック(iTunes)は、iTunesのメニューで「ファイル」->「ライブラリ」->「ライブラリを整理」を選択して、「ファイルを統合」を実施
  2. 「ミュージック」内「iTunes」ディレクトリ配下に必要なファイルが作成される
  3. この「iTunes」ディレクトリを丸ごと、新Macの「ミュージック」へコピー
  4. 新MacでiTunesを「option」を押しながら起動すると、ライブラリを選択できるようになる
  5. 「ライブラリを選択」から「iTunes」内の「iTunes Library.itl」を選択すれば、移行完了

    写真

      1. 写真は、「ピクチャ」内に「写真 Library」があり、これを旧Macから新Macの同じ場所にコピぺ
      2. 新Macで「option」を押しながら「写真」を起動して、今コピーしてきたライブラリを選択して読み込む


      Podcast

        1. podcastで、かつでCDから取り込んだものがあって、これがpodcastでは見た目では存在するがファイルが見つからないと言われる
        2. podcastのファイルは、ユーザ/名前/ ライブラリ / Group Containers / 243LU875E5.groups.com.apple.podcastsのキャッシュフォルダーに保存されている
        3. これを同じ箇所にコピペすればいいかと思ったが状況変わらず
        4. そこで「ブック」の「ライブラリに追加」でオーディオブックとして使っていくことにする

        読めばわかるMACでのPATH設定を完全理解
        https://reffect.co.jp/windows/full_understanding_mac

        M1 Mac
        https://oku.edu.mie-u.ac.jp/~okumura/macosx/m1.html

        M1 Macの開発環境
        https://qiita.com/shibukawa/items/797b7cbb7e530842e6f7


         


        あと、まっさらなosのまっさらなmacを手に入れたら、まずはosアップデートしておくことが大事だと学ぶ。



        参考文献


        旧Macから新Macへ「移行アシスタント」なしで移行
        https://rikei-fufu.com/2019/10/27/post-2187-mac-migration/


        macOS Catalinaでは、iTunesの分割によりメディアファイルの扱いに変更が
        https://minatokobe.com/wp/os-x/macos-catalina/post-57359.html


        Apple SiliconにおけるHomebrewのベストプラクティス
        https://qiita.com/yujiod/items/56002a7cef5b5a3be3fb


        macOS 11 Big Sur compatibility on Apple Silicon #7857
        https://github.com/Homebrew/brew/issues/7857


        Homebrew
        https://brew.sh/index_ja

        HomebrewでいれたPythonの削除
        https://qiita.com/baozam/items/268906b5984a37239b7d



        Apple M1 チップ搭載の Mac で macOS を再インストール中にパーソナライズエラーが表示される場合
        https://support.apple.com/ja-jp/HT211983

        Appleシリコンを搭載したMacでmacOS復旧を使用する
        https://support.apple.com/ja-jp/guide/mac-help/mchl82829c17/mac




        Homebrew&Python 立て直し

        現状課題

        • macにもともと入ってるpythonにpipでやってた、これを仮想環境でやりたい
        • x86_64(rosetta)の方でやってた、これをarm64でやりたい


        python環境を作り直す

        1. 今のスで入れてるライブラリをとりあえず削除
        2. pip freeze | grep -v '@' | awk -F'==' '{print $1}' | sudo xargs pip uninstall -y
        3. brewのインストール https://brew.sh/ja/ に行って、コマンドをコピーして、と思ったが
        4. macOSをお使いの場合は新しい.pkgインストーラーをお試し下さい
        5. とのことなので https://github.com/Homebrew/brew/releases/tag/4.4.20 で.pkgを落としてきて実行
        6. ちゃんとbrewがインストールできたかの確認 brew help
        7. unknown or unsupported macOS version: :dunno (MacOSVersionError) と言われる
        8. brew update-reset とするといいらしい、やってみた
        9. brew help やったらいい感じになったらしい
        10. 現在の PATH を確認 $ echo $PATH
        11. PATH のどこかに /opt/homebrew/bin が含まれていればOK
        12. $ which brew 出力が /opt/homebrew/bin/brew になっていれば、正しく PATH が設定されている
        13. xzのインストール $ brew install xz
        14. pyenvとは?Pythonのバージョンを管理してくれるツール
        15. Homebrewコマンドでpyenvをインストールする $ brew install pyenv
        16. pyenvからPythonをインストールする。ここからはpyenvコマンドを使います。まずは、以下のコマンドを入力します。$ pyenv install --list pyenvでインストールできるバージョンが出力されます
        17. $ pyenv install 3.11.0
        18. pyenvのpathを通す(以下を追記した)
        export PYENV_ROOT="$HOME/.pyenv"
          export PATH="$PYENV_ROOT/bin:$PATH"
            eval "$(pyenv init -)"

            などとやってたんだが、pymc5を使いたくて、そしてpymc5はminiforgeがいいよというので、pyenv環境は全部削除して、brewでminiforgeを入れ直すことにした




            1. miniforgeインストール  $ brew install miniforge
            2. condaのバージョン確認 $ conda --version
            3. conda 24.11.3 versionを返してくれればcondaの準備はOKです
            4. $ which conda
            5. /opt/homebrew/bin/conda path追加した方がいいのかな?でも以下は実行できてるしな conda env list
            6. 仮想環境作成しつつ、python本体をインストール(causal impactが3.11じゃないと動かないかもなので)
            7. $ conda create --name pm5_env python=3.11

            /opt/homebrew/Caskroom/miniforge/base
            /opt/homebrew/Caskroom/miniforge/base/envs/pm5_env


            1. $ conda activate pm5_env  としても
            2. CondaError: Run ‘conda init’ before ‘conda activate’ と言われる
            3. https://manabi-corpeng.com/conda-activate-init-error/ をみて、
            4. 元はここ https://manabi-corpeng.com/miniconda-install/#index_id5
            5. $ conda init zsh
            6. として、ターミナル再度立ち上げ直すと
            7. $ conda activate pm5_env できて、
            8. $ python --version
            9. でpython 3.11.11と返ってきた。無事に仮想環境にpython本体のインストール完了

            1. pymc5をインストール https://www.pymc.io/projects/docs/en/latest/installation.html
            2. $ conda install -c conda-forge "pymc>=5"
            3. (arviz, graphviz, lumpy, pandas, scipyなども)
            4. $ conda install -c conda-forge seaborn prophet matplotlib ipykernel ipywidgets
            5. $ conda install -c conda-forge seaborn matplotlib ipykernel ipywidgets
            6. (prophetがないと言われた、statsmodelsも)
            7. できんな $ conda install -c conda-forge prophet
            8. prophet causal impactも入れてな https://facebook.github.io/prophet/docs/installation.html#python

            uname -m
            arm64


            imagemagickインストール

            1. $ brew install imagemagick
            2. python 3.13がインストールされちゃったのを削除する
            3. $ brew uninstall --ignore-dependencies python

            brewの要らなくなったのを削除

            brew cleanup → 古いキャッシュや不要ファイルを削除(推奨)
            brew cleanup --prune=0 → すべて のキャッシュと不要ファイルを削除
            brew autoremove → 依存関係がなくなったパッケージを削除
            rm -rf $(brew --cache) → キャッシュ全削除


            conda clean --all すべてのキャッシュ・不要ファイルを削除(推奨)



            仮想環境のをbaseに適用したい

            仮想環境をアクティベート
            $ conda activate myenv

            インストール済みパッケージをエクスポート
            $ conda list --export > myenv_packages.txt

            base 環境に適用
            $ conda activate base
            $ conda install --file myenv_packages.txt




            不要になった古い環境を削除
            conda remove --name pm5_env --all


            condaで今どんな仮想環境作ってたっけ?
            $ conda info --envs

            $ conda activate pm5
            $ conda deactivate
            $ conda activate base

            base環境をcopyしてそっちにいろいろインストールしたい
            $ conda create --name base_yyyymmdd --clone base

            $ conda install beautifulsoup4 lxml

            見つからない時はconda-forge指定で
            $ conda install -c conda-forge beautifulsoup4



            2020年9月30日水曜日

            Prophet by Python on Mac

            
            # pip3 install pystan
            # pip3 install fbprophet
            
            python3 -m pip install prophet
            python3 -m pip install --upgrade plotly
            


            2020年9月26日土曜日

            マイケル・サンデルの白熱教室2018

            哲学は机上の学問ではない、空想世界のものではない
            市民が暮らす現実社会にこそ必要
            差別はどんなときも正義に反することなのか
            収入や富の格差とどのように向き合えばよいのか
            国境をめぐる問題をどう考えるべきか
            民主主義の力が試されている

            1.移民

            難民の受け入れ、断る権利はあるのか?
            では移民の受け入れ、断る権利はあるのか?
            文化面での影響、経済面
            親の遺産を受け取る権利はあるのか?
            国境の概念は?
            出国を制限する権利はあるのか?
            帰属意識は?以前の国か?今の国か?
            愛国心


            2.AIは最適な恋人を探せるか

            AIは完璧なマッチングができるのかもしれないが我々人間はそれを望んでいるのか
            人間の医師とAI医師のどちらに手術してほしいか
            感情で動くからこそ人間に手術、延命措置してほしいのでは
            自動運転にどうプログラミングするか
            AIはコメディアンになれるか
            死んだ人のデジタルアバターを作ることは?
            冷や汗、心地悪さ、不完全さが人間には必要なのでは?


            3.人を見た目で選んでもいいのか

            どんな場合でも差別は正義に反するのか
            人種差別と見た目による差別は同じか違うか
            特定の人種を優遇的に採用することは許されるか
             あとに続く人への道を開くことにもなるのではないか
            特定の人種にだけ職務質問するのは許されるか
            空港のセキュリティーチェックでの差別は許されるか

            差別を受けると社会に対する信頼が薄れる
            より多くの機会を与え、より多様な社会を作り出す優遇的差別なら許されるのではないか
            アリストテレスのいう正義の定義「人間を平等に同じように扱うこと」
             真の議論は、平等とは何か、同じようなとはどのような点においてなのか、それを決めようとするときに生じる
             その答えは経済的原理によって決められるべきか

            差別に関する議論は簡単だと言われることがある
            なぜならほとんどの人は差別には反対だし、人間は平等に扱われるべきだと考えているからだ
            ところが実際に難しい選択、困難な決断に直面したとき、私たちはそれぞれに問い直すことを迫られる
            そもそも目的とは何か、その目的を達成するために私たちのどんな人間性が問われているのか
            どんなチャンスが広がり、なにが障害や犠牲になるのか
            どんな差別が不当でなにが妥当な差別なのか


            4.ロナウドの年収は高すぎる?

            ロナウドが教師の2000倍稼ぐのは公正なのか
             才能への評価なのか努力への評価なのか
             希望が、問題は社会の不平等にあることを見えなくしている
             社会が評価するのは努力だけではない、才能や素質もではないか
            生まれつきの才能、つまり運がその人の収入を左右するのは正義や公正に反することなのか

            レースの勝者は道徳的にも勝利に値するのか
            実力主義社会は貴族社会よりも公正といえるのか
             偶然、才能を持っていること、偶然、その才能が称賛される社会であること、両方揃ってたからロナウドがいられる


            もしあなたが金持ちだったら実力社会と偶然社会どちらを選ぶか
            金持ちのときは実力社会がいいという、達成感や満足感、誇りを自分に感じたいから
            一方、収入の低い恵まれない立場だったら、実力社会には住みにくさを感じるだろう
            今、社会から取り残されると感じる人々は、社会の不公平さだけに不満があるわけではない
            自分が尊重されていないと感じる
            収入が低く質素な生活を送っているのは努力が足りないからだ、他の人ほど価値がないからだと言われてるように感じる
            社会が実際に不平等であるという状況に加えて、それぞれの人に与えられた地位は本人の努力で決まるという考え方は地位が高くない人々にとってはとても腹ただしく感じる、屈辱的でさえある
            このように実力社会は所得や富の分配からだけでなく、人間の尊厳からも問題となる
            社会はすべての人にそのはたらきに見合った敬意を払えているのか

            古代ギリシャの政治哲学者は、分配的公正(配分の正義)について話し合った
            議論の中心は所得や富についてではなかった、社会的な役割や義務、名誉などについてであった
            その議論は今も続いている
            配分の正義は単に市場が求める価値や公平さだけの問題ではない
            人の名誉や尊厳に関わることでもある
            公正な分配をどうおこなうべきか、現在の民主主義社会の根底にある課題の一つである


            5.プライバシー

            警察は病院のDNAデータベースを利用していいか
            全国民のDNA情報の登録を義務づける制度に賛成するか
            保険会社に自分の情報を提供して値引きを受けるか
            Uberが乗客の情報を公開するのはプライバシーの侵害か
            プライバシーには固有の価値はあるのか、同意があればいいのか
            正しい同意さえあればプライバシーの侵害とは存在しなくなるのか

            エリック・シュミットがプライバシーの問題について質問されたときの答え
            あなたが誰にも知られたくないと思っていることは、そもそもそれをやること自体が間違いだったのではないですか?

            ネットの個人向け広告はプライバシーの侵害か
            自分のプライバシーで最も重要な問題は、見た動画?読んだ本?行った場所?

            古代ギリシャ、ソクラテスの時代、プライバシーが問題になることはなかった
            公の領域と個人の領域が区別されていたから
            公の領域、すなわち民主主義により価値を置き、実践を進めた
            個人の領域だけで生きる人々をイディオティスと呼んだ、これが愚か者イディオットの語源となった
            イディオティスは市民社会への参加を果たしていないと考えられていた
            だから古代の人々にとってプライバシーとは軽蔑の対象だった
            ところが現代では重要な価値を持つ難しい課題となっている

            プライバシーとは何か、なぜ重要なのかを説明するのが難しいのは、それが二次的な役割を担っているから
            公平な社会、自由な社会、民主主義的な社会を求めている、でも誰もプライベートな社会を求めてるとはいわない
            プライバシーはなにかしらの脅威に対抗するための価値をもつものだから
            高圧的で独裁的な国家からの脅威、市民を監視し反乱の芽を摘み取ろうとする国家からの脅威、
            なにかを売りつけようと私たちの動向を常に見続ける企業や調査会社、ソーシャルメディアからの脅威かもしれない
            現代はDNAとビッグデータの時代でもある
            民主的な社会に生きる市民にとって、プライバシーの意味を広く議論し、
            私たちをなにから守るものなのかを考え続けるのが重要

            公正な社会とは何か、平等とは、市民の義務や人間性の価値とは何か
            たとえ全員が同意する結論にたどり着かなくても大切なことを教えてくれる
            それこそ公共性の精神、お互いへの敬意の重要さである

            ときに激しい意見の対立が起きたとしても、公の場で議論を交わすことで民主的な社会に生きる市民としての資質が養われていく



            SARIMA

            東アジア積米国揚コンテナ荷動き予測におけるSARIMAモデルの適用性

            http://www.ide.titech.ac.jp/~hanaoka/finalversion-of-conference.pdf

            3.データの定常性
            ADF検定
            原系列に加えて差分系列を用いた理由は、原系列が非定常である場合、差分系列をとることによりデータが定常になることが多い(9)ため

            原系列 単位根は存在しなかった。差分系列の場合は、t値が-9.368と99%有意水準でも帰無仮説が棄却されない。これにより、差分系列の定常性が確認された。以上の結果を踏まえ、差分系列を用いてSARIMAモデルを開発し、その適用性を検証する

            4.モデル
            4-1モデル概要

            自己回帰項の次数(p)は、自身(荷動き量)の過去の値について、どこまで遡って説明変数として用いるかを示している。例えば、pが2であれば1期及び2期前の荷動き量をモデルの説明変数として考慮することになる

            階差の次数(d)については、分析に利用する時系列データが定常性を有するまでに必要となった階差数を示す。本研究では、3.で述べたように、一階の差分系列が定常性を有しているため、dは1となる。

            なお、原系列が定常性を有している場合は、dは0となる。

            移動平均項の次数(q)については、自身の過去の値の誤差について、どこまで遡って説明変数として用いるかを示している

            なお、本研究では月次データを用いているため、季節変動の期間(s)は12である可能性が高い(10)。このとき、季節自己回帰項の次数、季節階差の次数、季節移動平均項の次数はそれぞれP、D、Q、に入る数値の12倍前の値が説明変数として用いられる。例えばPが2であれば、12期及び24期前の荷動き量を説明変数として考慮する。

            4-2モデルのパラメータ特定
            コレログラム

            図3に差分系列の自己相関係数、図4に同偏自己相関係数

            破線内の領域は、標本の自己相関がゼロであるという検定の95%棄却域である。領域の外側に(偏)自己相関係数がある場合は、(偏)自己相関が少なくとも有意水準95%で存在する。図3を参照すると、12次、24次、36次において特に強い自己相関を有していることが分かる。これは1年周期の季節性が存在していることを示唆しているため、季節階差sは12とするのが適切と考えられる。そこで、本研究では、季節階差sは12とする。また、前節の単位根検定によって、1階の差分系列が定常性を有していることが分かった。そのため、d及びDは1とする。

            次に、p、q、P、Qの特定について検討する。図3及び図4を参照すると、自己相関と偏自己相関ともに3期ラグの相関が比較的高く、4期ラグで初めて自己相関係数、偏自己相関係数ともに95%水準で棄却される。

            SARIMAモデルでは、「おそらく原系列の」
            (偏)自己相関係数のコレログラムを参照するだけではラグ数を決定できない

            しかし、図3、4の「階差系列の」コレログラムを参照することにより、0≦p, q, P, Q≦3としてパラメータの目安を立てることができる(9)。p, q, P, Qについて、0~3を各変数に当てはめ

            最尤法で推定し、AICが最小となるモデルを同定

            5.モデルの診断
            5-1残差の定常性

            同定された「SARIMA」モデルが適切であれば、残差は定常性を持ち、(偏)自己相関を持たないことが分かっている

            同定されたモデルの残差の自己相関係数及び偏自己相関係数のコレログラムを示す。破線の内側の領域は自己相関の値がゼロであるという検定の95%棄却域を示している。つまり、(偏)自己相関係数が破線の内側に留まっていれば、モデルは適切であると判断される。両図より、(偏)自己相関係数は破線の内側にあり、同定されたモデルによる残差が(偏)自己相関を有さないことが確認できる 以上より、残差の定常性という点からモデルの妥当性を確認できた

            5-2実績値と再現値の比較

            (9)沖本竜義:経済・ファイナンスデータの計量時系列分析、朝倉書店、2010
            (10)山澤成康:実践計量経済学入門、日本評論社、2004






            時系列解析入門
            https://www.ai.u-hyogo.ac.jp/~arima/arima.pdf

            定常時系列の解析に使われるARMAモデル・SARIMAモデルとは?
            https://ai-trend.jp/basic-study/time-series-analysis/sarima_model/

            SARIMAモデルでは合計7個の次数があります。 時系列方向のARIMA( p,d,q )に加え季節差分方向のARIMA( P,D,Q )、さらには周期 s があるためです。 これをSARIMA( p,d,q )( P,D,Q )[ s ]と表記することがあります。 それぞれの次数に対し0か1を考えるとしても、 27=128 通りのモデルを考えなければなりません。 このような組み合わせ爆発の問題を回避するため、周期 s は作図や自己相関関数をもとに決め打ちし、季節差分の P,D,Qは低く抑えることがよく行われます。

            残差に関する4つのプロットを見ることができます。 左上から順に、標準化した残差の時系列プロット、残差のヒストグラムと正規分布(とKDE分布)の密度関数、残差の正規QQプロット、残差の自己相関関数です。 残差の自己相関は低くまとまっており、ほぼ問題ないと言えるでしょう。



            心理統計法at放送大学

            豊田秀樹 2017

            第3回

            MCMC法
            事後分布に従うパラメータを乱数として発生させ、パラメータを確率分布として表す

            HMC法 ハミルトニアンモンテカルロ法
            物理学分野の力学的エネルギーの原理を応用したMCMC法の一つの方法

            生成
            HMC法は、同時事後分布に従う乱数を、蛇口から水が流れるように継続的に生成する

            捨てる区間 burn in
            乱数の数 chain

            点推定量
             事後期待値 EAP
             事後中央値 MED
             事後確率最大値 MAP
              事後分布が正規分布だったら平均値と同じだし、EAP=MED=MAP
              一様分布だったら最尤値と同じ=標本平均と同じ

             点推定値の精度
              事後分布の散布度(分散や標準偏差)の小ささ=点推定値の精度


            第?回

            検定力分析
             適切な検定ができるようにサンプルサイズを決める
              大きすぎず小さすぎずに
              でもそれって順番逆じゃね?
              サンプルサイズは実験者が主体的に決めることだべ


            第10回

            有意性検定は結果がシンプルでいい
            ブラックボックスでもいい
            統計熟知してない人には特にそう思われやすい
            有意水準を絶対的なものとして捉えちゃうので

            でも本当は同じ5%でも、
            サンプル数が多くてp<0.05になった場合(第一種の過誤が起きてる)もあれば、
            サンプル数が小さくてp>0.05になった場合(第二種の過誤が起きてる)場合もあるのに、絶対唯一視されてしまうという危険性がある

            サンプル数が多くて無意味な場合
            サンプル数が少なくて意味のある差を検出できない場合


            差がある確率は80%といわれると解釈は人によって分かれる
             書いた人が差があると思っても査読者はそう思わないかもしれない

             だが判断を各自が自在にできるのがベイズ推定のよきところともいえる
             サンプルサイズで結果の意味が変わることはない


            ABテストの結果、AがBを上回る確率は60%でした、と報告する
            BをAに切り替えるのにほぼコストがかからないのであれば、Aに切り替えようという判断がしやすい

            一方、AB間に差があるとはいえない、と報告する
            BをAに切り替えるのにほぼコストがかからないとはいえ、どっちつかずの報告ではAに切り替える判断はしにくい
            その結果、Aに切り替えていれば60%の確率で売上が増えたかもしれない未来を捨てている、機会損失が起きている
            でもそのこと自体に気づかないままに時は過ぎていく、これが怖い


            第11回

            オッズ比 odds = p / (1-p)

            チームAがBに勝つ確率が0.2と予想されている場合は
            0.2 / (1-0.2) = 1/4となる
            Aが勝つと予想している人が、Bが勝つと予想している人の1/4である

            オッズ比=賭けに勝った人の払い戻し倍率の逆数ともいえる
            Aに1,000円賭けてAが勝った時は、外れた人の掛け金をみんなもらい
            元金+4000円をもらえる


            2項分布の掛け合わせ(2x2のクロス数表、男女別のブランド認知率)
             男女間にブランド認知に差はあるか?などを調べる場合は
             リスク差、リスク比、オッズ比をみる
              有意性検定のカイ二乗検定と同じ


            第13回

            単回帰分析における回帰直線は、目的変数と説明変数のおおまかな関係を示してくれて便利
            だが説明変数では説明しきれない目的変数の特徴を考察することも大事、そのためには残差プロット

            ある2つの観測データにおいて、説明変数の値は同程度なのに、残差に大きな違いがあったりする、その違いが何かはわからない
            でもその違いはなぜかを考えることにより新たな別の説明変数を着想するきっかけになる

            残差プロットは新しい研究視点を与えてくれることもあり、観測対象に対する有用な知見を示してくれる

            2020年6月14日日曜日

            渡辺澄夫

            渡辺澄夫
            http://watanabe-www.math.dis.titech.ac.jp/users/swatanab/index-j.html

            データ解析
            http://watanabe-www.math.dis.titech.ac.jp/users/swatanab/da2019.html

            特異モデルにおけるベイズ検定と変化点発見への応用
            http://watanabe-www.math.dis.titech.ac.jp/users/fujiwara/doc/fujiwara_ibis2006.ppt.pdf

            Pythonや機械学習を学ぶ

            機械学習の前に重要なデータ抽出・加工に便利なPythonライブラリ「pandas」の基本的な使い方のチュートリアル
            https://www.atmarkit.co.jp/ait/articles/1802/13/news012.html


            [Python入門]リストの操作 (1/4)
            https://www.atmarkit.co.jp/ait/articles/1906/04/news009.html

            時系列データへの回帰分析
            https://logics-of-blue.com/time-series-regression/


            【Python】pandasのDataframe操作
            http://canisterism.hatenablog.com/entry/2018/01/07/150105


            #特定のセルの値を取り出してseriesに
            pythonでexcelファイル処理まとめ
            https://qiita.com/hasepy/items/06d5d2e2b6495752442c


            [Python] Excelで文字化けしないCSVファイルを書き出す
            https://qiita.com/y4m3/items/674423b596284bbc7cf7

            Pythonの日本語処理
            http://www.wakayama-u.ac.jp/~kazama/lab/python/i18n.html
            標準出力の文字コードと自動変換
            https://www.javadrive.jp/python/japan/index2.html
            文字コードの指定
            https://www.javadrive.jp/python/japan/index1.html
            Unicode文字列(ユニコード文字列)
            https://www.javadrive.jp/python/string/index5.html

            日本語文字列コード問題まとめ
            http://python.matrix.jp/pages/tips/string/encoding.html

            python3で日本語を含むURL(日本語URL)にurllibでアクセスする際、htmlで勝手にencodeされてエラーするので回避策をメモ
            https://qiita.com/mix/items/87d094414e46f857de45

            日本語を含むURLでつまづく
            http://mankuro.xyz/blog/2017/04/25/japanese-url/
            単一ドメインを走査する(URLに日本語を含む場合)
            http://nnpo.hatenablog.com/entry/2016/12/13/002540
            PythonでURLエンコード/デコード
            http://shuzo-kino.hateblo.jp/entry/2016/10/22/224034

            pythonでutf-8日本語文字列を、URIエンコード・URLデコードする
            http://linux.oboe-gaki.com/archives/000333.html
            Pythonでマルチバイト文字を扱う際に気をつける点。
            https://gist.github.com/devlights/4561968
            Python と文字コード
            http://www.kabipan.com/computer/python/unicode.html


            [Python] urllib.parseによるURLエンコード/デコードの方法
            https://hibiki-press.tech/learn_prog/python/url-encoding/2804



            機械学習

            第1回 難しくない! PyTorchでニューラルネットワークの基本
            https://www.atmarkit.co.jp/ait/articles/2002/06/news025.html

            AI・機械学習のための数学超入門 ― 前提知識は四則演算だけ! (1/4)
            https://www.atmarkit.co.jp/ait/articles/2003/02/news023.html

            機械学習やディープラーニングってどんなもの? (1/2)
            https://www.atmarkit.co.jp/ait/articles/2003/24/news016.html

            「機械学習の最先端」を効率的に情報収集! おすすめのメルマガ3選
            https://www.atmarkit.co.jp/ait/articles/2006/11/news016.html

            機械学習の手法13選 ー 初級者、中級者別に解説!
            https://ainow.ai/2020/06/04/222969/

            スターバックスはコーヒー事業者ではない ― データテック企業なのだ
            https://ainow.ai/2020/05/28/222388/


            平均二乗誤差

            pytorchにはMSELossがある

            criterion = torch.nn.MSELoss()

            y = f(x)
            loss = criterion(y, t)
            print(loss.data)

            自作するとこう
            def mycriterion(x, y):
                result = (x - y) ** 2
                return result.sum() / len(result)


            myloss = mycriterion(y, t)
            print(myloss)





            2020年5月30日土曜日

            SSブログとGoogleフォトのアルバム

            So-netブログ改めSSブログは、Googleフォトの画像を埋め込むことができる。
            ブログ側にてアップした画像は、以前は同じアルバムに入ってた。
            2019年3月ごろからはアップしたタイミングごとに別のアルバムになった。

            2020年3月ごろから、ブログ閲覧者はGoogleアカウントにサインインしないと画像が見れなくなっていた、ことに3ヶ月くらいしてから気づいた。

            見れるようにするには、Googleフォトにて、アルバムを共有設定にする必要がどうやらあるらしい。。。



            SSブログやBloggerからアップした画像を削除したい場合


            Googleアルバムアーカイブというところにアクセスする必要があるらしい



            2020年5月24日日曜日

            Pythonで体験するベイズ推論

            Pythonで体験するベイズ推論 PyMCによるMCMC入門
            キャメロン デビッドソン=ピロン(著) 玉木徹(翻訳)

            PyMC3のインストール方法

            岩波データサイエンス Vol.1
            [特集] ベイズ推論とMCMCのフリーソフト のサポートページ
            https://sites.google.com/site/iwanamidatascience/vol1/support_tokushu#TOC-PyMC3-

            Python ヒッチハイク・ガイド

            https://python-guideja.readthedocs.io/ja/latest/

            PcMC3のコード

            https://github.com/CamDavidsonPilon/Probabilistic-Programming-and-Bayesian-Methods-for-Hackers

            Chapter1の一部をやってみた

            https://github.com/sasasakaz/bayesian/blob/main/bayesian_estimation_for_change_point_detection.ipynb

            2020年4月12日日曜日

            2群の平均値の差の検定そしてベイズ推定

            背景
            • 2群の平均値に差はあるか?を簡便におこなうならt検定
            • 中心極限定理とt分布の頑健性のおかげで、たいていの場面において有用
            • 計算簡単でコスパに優れた方法だが、有意差がある/ない以上の情報はもたらしてくれない
            そこでベイズ推定
            • ここでは2群の観測データそれぞれがt分布から生成されると仮定したモデルを作成する
            • そしてこのモデルにより、2群の平均値の差の事後分布を得る
            • これにより2群の平均の差が一定値以上である確率など、豊かな情報を得ることができる
            結論
            • ベイズ推定においても、2群の平均の差の平均値や区間推定は、Welchのt検定とほぼ同じ結果が得られた
            • 弱情報事前分布の使用により事後分布はほぼ尤度だけで形作られ、しかも単峰だったため
            • 不確かさを扱いながらの推定は手間を要するが、手間をかけたぶん実務面での問いに答えやすい情報を得られた



            シナリオ

            • 背景: カフェチェーンの店頭ディスプレイ改善施策
              • あるカフェチェーンで、店内POP(販促物)を刷新することで「ラテ」の売上拡大を企図している
              • 立地や客層、売上規模、ラテの販売動向が似通っている2店舗を対象に、ABテストを模した実験をおこなった
            • データ構造と検証項目
              • 2店それぞれの14日間のラテ注文単価データ(日次ラテ売上金額 / 日次ラテ注文数)
              • ラテのサイズやトッピングの有無などにより変動しやすい売上金額ではなく注文単価で比較
              • 処置(テスト店舗での新POP)は結果変数(ラテの日次注文単価)に影響してそうかを検証したい

            観測データ

            A群(Control)[465.0, 458.6, 466.5, 475.2, 457.7, 457.7, 475.8, 467.7, 455.3, 465.4, 455.4, 455.3, 462.4, 440.9]

            B群(Test)[454.1, 471.6, 464.8, 484.7, 466.4, 458.8, 502.0, 476.6, 481.0, 458.6, 471.8, 481.7, 462.7, 485.6]

            Welch t-test

            Group A: mean=461.34, unbiased sample variance=81.62, n=14
            Group B: mean=472.89, unbiased sample variance=174.83, n=14
            calculated degree of freedom: 23.0
            
            

            Welch's t_test Results t-value: 2.70 p-value: 0.0128 average diff: 11.55 95%CI: (2.70, 20.41)




            統計モデリングのスタンス

            • 統計や機械学習においては、今手元にある観測データは、なんらかの確率分布から生成されたという考え方をする。

            • 例えばこのカフェの場合、ラテ注文者の金額は確率的に決まる(例えば10人中5人くらいは400円の注文をする)という考え方。

            • 例えば実際の注文額(観測データ)は、平均400円、ばらつき50円くらいの正規分布から発生したのだろうといった捉え方ができる。

            • 確率分布とパラメータ

              • ただし真の確率分布は誰にもわからない(本当は平均380円だったのかも?本当はもっと複雑な形状の分布だったのかも?)。
              • 分析者はなるべく真の確率分布に近しそうな確率モデルを構築する。この確率モデルの形状を決めるのがパラメータ。
              • 真の確率分布がわからない以上、適切な確率モデルもパラメータも分析者にはわからない。
              • 一方、手元には観測データがある。事実としてここにあるからには確からしいであろうと思える。
              • そこで、観測データは確からしいであろうを出発点として、このデータを生み出したパラメータを(観測データの生成メカニズムとは)逆向きに探るアプローチをとる。
            • パラメータの選定

              • 手元の観測データを得るのにちょうどいいパラメータもあれば、そうでないものもある。
              • 良し悪しの判断に用いるのは、データとパラメータの適合度合いを表す指標(likelihood 尤度)。
              • データを固定して、パラメータをいろいろと変化させたときに、尤度がどう変わるかをグラフや数式で表現したのが尤度関数(Likelihood Function)。
            • 古典的統計学の場合

              • 尤度が一番しっくりくる箇所を特定してパラメータを推定する(例えば二次関数を微分して極値を求める最尤法など)。t検定の考え方もこれに準ずる。
              • 計算が速く推定結果がわかりやすい。しかしそのピンポイントのわかりやすさが仇になる場合もある。
            • 不確実性

              • Welchのt検定の結果、新POP導入でTest店のラテ注文単価はControl店を平均的に上回っていたことがわかった。
              • だが、14日間のテスト期間中には注文単価が同程度だった日や下回っている日もあった。
              • t検定が教えてくれるのは「平均して効果があったかどうか」という1点。
              • 14日間という限られた観測データから得られた推定値が、不確実性をどの程度含んでいるかは見えない。
              • テスト期間の傾向が今後も続くのか、他店導入時に裏目に出るリスク(単価が下がる確率)はどのくらいかなど実務面での問いには答えにくい。
            • パラメータの不確かさを含んだ推定

              • であれば、今手元にある限られた観測データから生じる「パラメータの不確かさ」を含んだままに推定してみる。
              • これにより、まだ見ぬ場面における不確かさを確率的に表現しやすい、使い勝手のいい推定結果を得ることができるのではないか。
              • そこで、尤度以外の情報(すでにわかっている知識、過去経験など)も駆使しながら不確かさをうまく扱えるベイズ推定をおこなう。
            • ベイズ推定の場合

              • ベイズ推定では探索によって得られるパラメータを確率分布(事後分布)で表す。
              • メリットとして、推定値の不確かさを自然に表現しやすく、実務面での問いにも答えやすい情報を得られる。
              1. まずパラメータの探索範囲を確率分布(事前分布)で仮定する。
              2. 次に手元の観測データと事前分布を足がかりにして探索する。
              3. こうしてパラメータの不確かさを考慮した推定値(事後分布)を得る。
                 ※事前分布に、データから得られた尤度(情報)を掛け合わせる(更新する)ことで、事後分布を得る

            なお尤度はあくまで分析者が仮定した確率モデルのパラメータとの適合度合いを表すだけ。観測データとパラメータとの辻褄がもっとも合う尤度だったからといって、最適解のパラメータであることを常時保証してくれるわけではない。




            Bayesian Model Definition

            • ベイズ推定のモデリングで分析者が設定すること

              • 観測データの生成プロセス(尤度関数となる確率分布の選定): 観測データがどんなルール(確率モデル)から生まれたか
              • 選んだ確率モデルの形状を決めるパラメータの事前分布: 確率モデルの平均やバラツキをコントロールするパラメータの探索範囲
            • 観測データの生成プロセス

              • 2群の観測データそれぞれが「t分布」から生成されると想定
                • t分布は、平均mu 標準偏差std 自由度ν(ニュー)の3つのパラメータで形状が決まる
                • t分布は、正規分布よりも両端が厚いぶん、観測データに極端な値があった場合に、たまたま起きたノイズ(標本誤差)として処理しやすい
                • t分布は、νが大きくなるにつれて正規分布に近似していく(t分布を想定することで正規分布をも包含できる)
                • t分布にすることで、小サンプルでも標本誤差を軽減しやすく、不確かさを考慮した「頑健な」推定がしやすい
            • 各パラメータの事前分布

              • muとstd共通
                • muとstdの事前分布はかなり広めに設定している(弱情報事前分布 Weakly Informative Prior)
                • 真の値がどのあたりに位置するか確からしい情報がない(観測データを最優先したい、あまり影響与えたくない)との考えを反映
                • この場合、事後分布はほぼ観測データの情報(尤度)だけで形作られる(ので推定結果は検定の結果と近しくなりやすい)
              • mu
                • 観測データ全体での平均と、観測データ全体の標準偏差を2倍した標準偏差からなる、裾が長い正規分布としている
              • std
                • 観測データ全体のスケールから機械的に算出した、範囲広めの一様分布としている
                • 下限は0付近ギリギリまで探索できるように設定(標準偏差は0以下にはならない、0近辺に張り付く可能性ある)
                • 上限は現実的範囲に制限
              • ν(ニュー)
                • 頑健な推定のためにνの値が小さい(=両端が厚い分布になる)方に高い事前確率を割り当てたい
                • 0をピークに右に裾が長い指数分布は好都合だが、νは0より大きい必要がある。またt分布はνが30を超えるとほぼ正規分布になる(ν=1はCauchy分布と同じ)
                • 以上から平均29(ラムダλ=1/29)の指数分布を右に1だけシフトしている
                • これにより観測データの外れ値を許容しやすいν=1近辺(典型的なt分布)から、ν=30近辺(ほぼ正規分布)まで広く探索できる
            • 関心のある指標自体もモデリング

              • 観測データの生成プロセスを推定するついでに、結果の判断や意思決定に有用な情報もモデル化する
              • ここでは以下4指標をDeterministic (各種パラメータから導出される決定論的変数)に推定する
                • 平均の差分: リフト差分(Test群の平均 - Control群の平均)
                • 標準偏差の差分: バラツキの差(Test群の標準偏差 - Control群の標準偏差)
                • 効果量: 差の大きさがバラツキに対してどれだけインパクト(大きな効果、意味を持つ差)があるか
                • 平均の変化率: リフトの比率(Control群を基準としたときの相対比率 1=100%すなわち等倍)
            # Model Definition
            
            # x_A:Control, x_B:Test
            x_A = [465.0, 458.6, 466.5, 475.2, 457.7, 457.7, 475.8, 467.7, 455.3, 465.4, 455.4, 455.3, 462.4, 440.9]
            x_B = [454.1, 471.6, 464.8, 484.7, 466.4, 458.8, 502.0, 476.6, 481.0, 458.6, 471.8, 481.7, 462.7, 485.6]
            
            # prior distributions of mu 観測データの全体から設定
            combined_data = np.concatenate([x_A, x_B])
            pooled_mean = combined_data.mean()
            pooled_std = combined_data.std() * 2
            
            # prior distributions of sigma データのスケールに応じて動的に設定
            std_low = pooled_std * 0.001
            std_high = pooled_std * 10
            
            # prior distributions of nu クルシュケさんのベストプラクティスに準じる
            lambda_kruschke = 29
            
            # 平均と標準偏差それぞれの2群間差分、効果量、平均の相対比率についてもモデル作成
            
            with pm.Model() as model_weakly:
                mu_A = pm.Normal('mu_A', mu=pooled_mean, sigma=pooled_std)
                mu_B = pm.Normal('mu_B', mu=pooled_mean, sigma=pooled_std)
                # muが負の値を取るのを完全に防ぐなら、TruncatedNormalを使いlowerを指定する方法もあり
                # lower=0よりは、ドメイン知識を反映して、ラテの最低価格にするのがより現実的
                # mu_A = pm.TruncatedNormal('mu_A', mu=pooled_mean, sigma=pooled_std, lower=0)
                # mu_B = pm.TruncatedNormal('mu_B', mu=pooled_mean, sigma=pooled_std, lower=0)
            
                std_A = pm.Uniform('std_A', lower=std_low, upper=std_high)
                std_B = pm.Uniform('std_B', lower=std_low, upper=std_high)
                nu_kruschke = pm.Exponential('nu', lam=1/lambda_kruschke) + 1
            
                obs_A = pm.StudentT('obs_A', mu=mu_A, sigma=std_A, nu=nu_kruschke, observed=x_A)
                obs_B = pm.StudentT('obs_B', mu=mu_B, sigma=std_B, nu=nu_kruschke, observed=x_B)
            
                mu_diff = pm.Deterministic('mean_diff', mu_B - mu_A)
                mu_diff_rr = pm.Deterministic('relative_mean_diff', mu_diff / mu_A)
                std_diff = pm.Deterministic('std_diff', std_B - std_A)
                effect_size = pm.Deterministic('effect_size', mu_diff / np.sqrt((std_A**2 + std_B**2) / 2))
            
            
            # MCMC Sampling
            with model_weakly:
                prior_weakly = pm.sample_prior_predictive()
                trace_weakly = pm.sample(tune=2000, draws=2000, random_seed=42, return_inferencedata=True, chains=4, 
                                        #  target_accept=0.95,  # Uncomment if divergences occur (Raise to 0.9-0.95)
                                         idata_kwargs={"log_likelihood": True})  # モデル比較に使用する対数尤度を保存
                posterior_predictive_weakly = pm.sample_posterior_predictive(trace_weakly)
            



            Sampling Quality Check

            • ベイズ推定においては、サンプリング(マルコフ連鎖)が正常に機能し、事後分布に正しく収束しているかを確認する必要がある

            • trace_plotとsummaryを確認し、基準値をクリアしていれば適切な推定結果と解釈しやすい

            • trace_plotによる視覚的チェック

              • 左側はKDE(カーネル密度推定)による事後分布の形状、右側はサンプリングの軌跡(トレースライン)。いずれのグラフもchainsで指定した本数(例: 4本)の線がプロットされる
              • 左側のグラフでは4本の線がだいたい同じ形に、右側のグラフでは毛虫のような見た目(縦軸の値が一定範囲を何度も行き来して変動幅がだいたい同じくらい)になっていれば概ね問題ない
              • もしも左右グラフの下部に縦のバーが表示されている場合は、divergence 発散が起きていることを表す(縦バーの箇所ではサンプラーが空間の急斜面で足を踏み外してる、シミュレーションが真の軌道から大きく外れてる、つまりサンプリングがうまくいっていないことを表す)
                • 対処策1: target_acceptの値を0.90〜0.95程度に上げてみる(歩幅を細かくして慎重に探索させる)
                • 対処策2: tuneの回数を増やしてみる(ウォーミングアップ期間を伸ばして、地形の学習を確実にする)
            • summaryによる数値的チェック

              • r_hat
                • chain間の不一致度を表す
                • 目安として1.05以下(理想は1.00)であれば問題ない
                • そうなってない=各chainが同じ分布にたどり着いていない(収束していない)、つまりサンプリングがうまくいっていない
              • mcse_mean, mcse_sd(マルコフ連鎖モンテカルロ誤差)
                • サンプリングのブレが原因で生じる推定値の誤差(の平均と標準偏差)を表す
                • 目安としてmcse_meanが0.01以下(パラメータの変動範囲が0〜1の場合)、またはパラメータの標準偏差の5%以下(できれば2%以下)と十分に小さければ問題ない
              • ess_bulk, ess_tail(有効サンプルサイズ)
                • 自己相関を考慮した実質的なサンプル数
                • 事後分布の形状やHDIを安定して推定できているかを表す
                • 目安として400以上(できれば数千)確保されていれば問題ない
            • plot_autocorrによる自己相関チェック(任意)

              • summaryでess_bulkとr_hatが基準値をクリアしていれば自己相関は心配無用なので実行せずともよい
              • 問題ありの場合は、該当のパラメータのみを指定して実行(することでグラフが少ないぶん見やすい)
              • どこに問題あるかの原因の切り分けに役立つ
                • 特定のchainだけ自己相関が高い→tuneを増やす、サンプリングの初期化オプションを調整するなど
                • どのchainも自己相関が高い→モデルの構造を変える(パラメータ間の相関などが疑われる)
            # trace_plot
            az.plot_trace(trace_weakly)
            plt.tight_layout();
            
            # summary
            az.summary(trace_weakly)
            
            # mcse_meanが各パラメーターの標準偏差の5%以下(できれば2%以下)という基準値に収まっているかをチェック
            summary_df = az.summary(trace_weakly)
            summary_df['mcse_mean / sd'] = summary_df['mcse_mean'] / summary_df['sd']
            summary_df['mcse_mean / sd (%)'] = (summary_df['mcse_mean'] / summary_df['sd']) * 100 
            output_df = summary_df[['sd', 'mcse_mean', 'mcse_mean / sd', 'mcse_mean / sd (%)']]
            rounded_df = output_df.round({'sd': 1, 'mcse_mean': 3, 'mcse_mean / sd': 4, 'mcse_mean / sd (%)': 2 })
            rounded_df
            
            # # 自己相関
            # az.plot_autocorr(trace_weakly, var_names=["nu"], figsize=(8,3), textsize=10)
            # plt.tight_layout();
            
            # forestplot 
            # HDIを一覧で視覚的に解釈しやすい(太線は50%HDI)
            az.plot_forest(trace_weakly, figsize=(6,4), textsize=10);
            



            PPC

            1. 事後分布のchainから任意のパラメータをランダムに取り出す(例: mu_A=450 std_A=20 nu=5)
            2. 取り出したパラメータから成る分布から、観測データと同じサンプルサイズの擬似データを生成する(t分布から14サンプル取り出す)
            3. このKDE(カーネル密度推定)をプロットしたのが青線
            4. ここまでを指定の数(num_pp_samples=100)繰り返す。観測データのサンプルサイズが多い場合や分布次第では、青線が帯のように密集状態になる
            5. 青線の平均をとったのがオレンジ点線(=モデルの平均的な予測)
            • 読み解き方

              • 黒線(観測データのKDE)が青線の変動範囲やオレンジ線と同じような位置、形であれば、モデルは観測データをよく近似していると解釈できる
              • 大きくズレていたら、分布の選定や事前分布の見直し、例えばt分布以外がよかったかな?事前分布の探索範囲を変えた方がよい?など、モデル修正方針の検討材料になる
              • あくまで今手元にある観測データの発生メカニズムを矛盾なくシミュレーションできているかを見てるだけ。観測データやモデル自体の確からしさを裏付けるものではない(観測データが偏ってる可能性や過学習リスクは残る)
            • 本件の場合

              • 観測データのサンプルサイズが少ないため、青線はあまり密集していない
              • 黒線がモデルの予測範囲(青線たちの広がり)の中に収まっており、いい感じのモデルといえそう
              • ダメなモデルだったら、黒線が青線たちの外側に大きく飛び出していたり、山の位置が全くズレてたりするだろう
              • muの事前分布をNormalにしたことで、ごく僅かに左端がマイナスの値を取る。これを100サンプルが引き当てた場合には、違和感のあるプロットになる。2群の平均値の差の事後分布にはほぼ影響ないが、どうにも気になる場合はTruncatedモデルを採用する手もある
            az.plot_ppc(posterior_predictive_weakly, num_pp_samples=100, figsize=(10, 4));
            



            Interpretation

            • Posterior Inference and Interpretation: 推論された事後分布の解釈
            • plot_posterior
              • 事後分布のKDE, mean,HDIを一覧表示。視覚的に判断しやすい
              • ref_valで指定した値を基準に、その値を上回る(下回る)確率を表示することも可能
            • 2群の平均値の差について詳しく
              • もっとも関心のあるところなので加工してグラフにいろいろ装飾している
            # posterior
            az.plot_posterior(trace_weakly, figsize=(10,6), textsize=10)
            plt.tight_layout();
            
            # posterior
            # 差分、効果量、平均の変化率のmeanやhdiの表示
            
            az.plot_posterior(trace_weakly, # hdi_prob=0.95,
                              var_names=["mean_diff", "relative_mean_diff"],
                              ref_val=0, color='#87ceeb', figsize=(8,2), textsize=10);
            
            az.plot_posterior(trace_weakly, # hdi_prob=0.95,
                              var_names=["std_diff", "effect_size"],
                              ref_val=0, color='#87ceeb', figsize=(8,2), textsize=10);
            
            
            
            # 下準備
            
            # 多次元配列を一次元のサンプル配列として抽出
            mu_diff_samples = az.extract(trace_weakly, var_names="mean_diff").values
            
            # posterior_meanと94%HDIをグラフに表示するために値取得
            posterior_mean = mu_diff_samples.mean()
            hdi_lower = np.percentile(mu_diff_samples, 3)
            hdi_upper = np.percentile(mu_diff_samples, 97)
            
            
            # 2群間の平均値の差分の事後分布を表示
            fig, ax = plt.subplots(figsize=(6,4))
            ax.hist(mu_diff_samples, bins='auto', density=True,  # 縦軸を確率密度(全体の面積が1)にする
                    color="tab:orange", alpha=0.5)
            # bins='auto'にすると、データの四分位範囲とサンプルサイズから、外れ値に影響されにくい最適なビン幅を自動計算してくれる
            # density=Trueにすると、ヒストグラムの面積の合計が1になる(確率密度関数と同じ状態)になる!
            
            ax.axvline(0, lw=0.8, linestyle="dashed")  # ゼロのタテ線
            
            # observed_meanと95%CIの描画(観測データの平均値と95%信頼区間)
            # y位置を決める(グラフの一番下から少し上げた高さ)
            ymin, ymax = ax.get_ylim()
            ci_y = ymin + 0.07 * (ymax - ymin)
            ax.scatter(diff_mean, ci_y, s=30, facecolors="white", edgecolors='gray', linewidths=2, label= f"Observed Average: {diff_mean:.2f}" , zorder=5)  # mean の点
            ax.hlines(y=ci_y, xmin=ci_lower_w, xmax=ci_upper_w, color='gray', linewidth=3, label=f"95% CI: [{ci_lower_w:.2f}, {ci_upper_w:.2f}]")  # 95%CIの横線
            
            # posterior_meanと94%HDIの描画(ベイズ推定での事後分布)
            # y位置を決める(グラフの一番下から少し上げた高さ)
            ymin, ymax = ax.get_ylim()
            hdi_y = ymin + 0.03 * (ymax - ymin)
            ax.scatter(posterior_mean, hdi_y, s=30, facecolors="white", edgecolors='#7f2704', linewidths=2, label= f"Posterior Average: {posterior_mean:.2f}" , zorder=5)  # mean の点
            ax.hlines(y=hdi_y, xmin=hdi_lower, xmax=hdi_upper, color='#cc5500', linewidth=3, label=f"94% HDI: [{hdi_lower:.2f}, {hdi_upper:.2f}]")  # 94%HDIの横線
            
            ax.legend(loc='upper right')
            ax.set_xlabel("Difference in Average (JPY, Test - Control)", fontsize=10)
            ax.set_ylabel("Probability Density (Area integrates to 1)", fontsize=10)
            ax.set_yticklabels([])  # y軸の目盛りラベルを非表示にする(確率密度関数の値自体に意味を見出さなくていいように)
            ax.tick_params(axis='y', which='both', length=0)  # y軸の目盛り線の長さを0にして非表示状態にする
            # ax.get_yaxis().set_visible(False)  # これだとlabelも非表示になる
            ax.set_title("Estimated Lift of Latte \n(t_dist Weakly Prior Model)", fontsize=12)
            plt.tight_layout()
            plt.show()
            
            # print('observed average: {0:,.2f} 95%CI: ({1:,.2f}, {2:,.2f})'.format(diff_mean, ci_lower_w, ci_upper_w))
            # print('posterior average: {0:,.2f} 94%HDI: ({1:,.2f}, {2:,.2f})'.format(posterior_mean, hdi_lower, hdi_upper))
            
            
            



            Informative Model

            • ベイズ推定っぽく、事前分布に事前情報を適用したモデル
            • 他チェーンでは新POPで単価が50円上がったらしいという事前情報を反映した事前分布に書き換える
            • 「Test店はControl店よりもあらかじめ50円くらい高くなるポテンシャルを秘めているはずだ」との考えを反映したモデル
            • 尤度関数は引き続きt分布を想定
            • 想定される弱事前情報分布モデルからの変化
              • Test店の平均値と94%HDIが上ブレする。ベイズ推定は「他チェーンでは50円上がったらしいけど、今回のデータは11円か…じゃあ間をとってこれくらいが真の実力かな」という、データの不確実性と過去の信頼性を天秤にかけた、いわゆる「収縮効果(Shrinkage)」を起こす。
              • ひょっとすると94%HDIが狭まるかも。ベイズ推定は「情報が増えて、より確信を持って(不確かさを減らして)真の値を予測できるぞ」という状態になるので、事後分布の山が尖って、94%HDIの横棒が95%CIに比べて狭く引き締まる可能性がある。
            # Model Definition
            
            with pm.Model() as model_informative:
                # A店は、手元のデータの全体平均をベースに緩やかに置いておく
                mu_A = pm.Normal('mu_A', mu=pooled_mean, sigma=pooled_std)
                # B店(Test群)の事前分布に「50円プラス」の知識を組み込む。
                # 過去の実績(50円アップ)を信じつつ、ブレ(sigma)も考慮する
                prior_B_mean = pooled_mean + 50 
                mu_B = pm.Normal('mu_B', mu=prior_B_mean, sigma=pooled_std) 
            
                std_A = pm.Uniform('std_A', lower=std_low, upper=std_high)
                std_B = pm.Uniform('std_B', lower=std_low, upper=std_high)
                nu_kruschke = pm.Exponential('nu', lam=1/lambda_kruschke) + 1
            
                obs_A = pm.StudentT('obs_A', mu=mu_A, sigma=std_A, nu=nu_kruschke, observed=x_A)
                obs_B = pm.StudentT('obs_B', mu=mu_B, sigma=std_B, nu=nu_kruschke, observed=x_B)
            
                mu_diff = pm.Deterministic('mean_diff', mu_B - mu_A)
                mu_diff_rr = pm.Deterministic('relative_mean_diff', mu_diff / mu_A)
                std_diff = pm.Deterministic('std_diff', std_B - std_A)
                effect_size = pm.Deterministic('effect_size', mu_diff / np.sqrt((std_A**2 + std_B**2) / 2))
            



            Truncated Model

            • 結果変数が負の値をとらないようにするモデル
            • 弱情報事前分布モデルも事前情報を組み込んだモデルも、muの事前分布をNormalにしていた
            • 推定への影響は軽微だが、現実世界のドメイン知識をより厳密に反映したモデルにする
            • 尤度関数は引き続きt分布を想定しつつ、muの事前分布をTruncated Normalに変更する
            • ドメイン知識を反映したモデルで納得感高めることを企図(副次的にPPCでの違和感ある出力回避可能)
            with pm.Model() as model_truncated:
                # muが負の値を取るのを完全に防ぐなら、TruncatedNormalを使いlowerを指定する方法もあり
                # lower=0よりは、ドメイン知識を反映して、ラテの最低価格にするのがより現実的
                mu_A = pm.TruncatedNormal('mu_A', mu=pooled_mean, sigma=pooled_std, lower=0)
                mu_B = pm.TruncatedNormal('mu_B', mu=pooled_mean, sigma=pooled_std, lower=0)
            
                std_A = pm.Uniform('std_A', lower=std_low, upper=std_high)
                std_B = pm.Uniform('std_B', lower=std_low, upper=std_high)
                nu_kruschke = pm.Exponential('nu', lam=1/lambda_kruschke) + 1
            
                obs_A = pm.StudentT('obs_A', mu=mu_A, sigma=std_A, nu=nu_kruschke, observed=x_A)
                obs_B = pm.StudentT('obs_B', mu=mu_B, sigma=std_B, nu=nu_kruschke, observed=x_B)
            
                mu_diff = pm.Deterministic('mean_diff', mu_B - mu_A)
                mu_diff_rr = pm.Deterministic('relative_mean_diff', mu_diff / mu_A)
                std_diff = pm.Deterministic('std_diff', std_B - std_A)
                effect_size = pm.Deterministic('effect_size', mu_diff / np.sqrt((std_A**2 + std_B**2) / 2))
            



            Gamma Model

            • Truncated Model同様に、結果変数が負の値をとらないようにするモデル
            • 尤度関数はガンマ分布を想定
            • 負の値をとらない連続値であれば、t分布と切断分布の組み合わせよりは、こちらの方が汎用性は高いかも
            # Model Definition
            
            with pm.Model() as model_gamma:
                # ガンマ分布のパラメータは「正の実数」でないとなので弱情報事前分布としてExponentialやHalfNormalを使うことが多い
                alpha_A = pm.Exponential('alpha_A', lam=0.1)
                beta_A = pm.Exponential('beta_A', lam=0.1)
                alpha_B = pm.Exponential('alpha_B', lam=0.1)
                beta_B = pm.Exponential('beta_B', lam=0.1)
            
                obs_A = pm.Gamma('obs_A', alpha=alpha_A, beta=beta_A, observed=x_A)
                obs_B = pm.Gamma('obs_B', alpha=alpha_B, beta=beta_B, observed=x_B)
                
                # ガンマ分布の数理特性から、事後分布の平均と標準偏差を逆算する(deterministic用)
                # 各群の期待値(平均値 = alpha / beta)の計算
                mu_A_calc = pm.Deterministic('mu_A_calc', alpha_A / beta_A)
                mu_B_calc = pm.Deterministic('mu_B_calc', alpha_B / beta_B)    
                # 各群の標準偏差(sd = sqrt(alpha) / beta)の計算
                std_A_calc = pm.Deterministic('std_A_calc', np.sqrt(alpha_A) / beta_A)
                std_B_calc = pm.Deterministic('std_B_calc', np.sqrt(alpha_B) / beta_B)
            
                # 平均と標準偏差それぞれの2群間差分、効果量、平均の相対比率についてもモデル作成
                mu_diff = pm.Deterministic('mean_diff', mu_B_calc - mu_A_calc)
                mu_diff_rr = pm.Deterministic('relative_mean_diff', mu_diff / mu_A_calc)
                std_diff = pm.Deterministic('std_diff', std_B_calc - std_A_calc)
                effect_size = pm.Deterministic('effect_size', mu_diff / np.sqrt((std_A_calc**2 + std_B_calc**2) / 2))
            



            Compare Models

            • どの尤度関数(モデル)が優れているかを比較
            • 事後分布を丸ごと使って比較する
            • LOOやWAICといったベイズ専用の指標を計算する。
            • 単に手元のデータへのフィット度を見るだけでなく、「パラメータの不確実性も含めた上で、未来の予測能力が一番高いのはどのモデルか?」を厳密にスコアリングしてくれる。
            • 基本的には WAIC よりも LOO を使う方が推奨とされている。
              • 理由は数理的な頑健性(ロバストさ)にある。
              • WAIC: 計算がめちゃくちゃ高速だけど、データが少なかったり、極端な外れ値があったりすると、ペナルティ項(p_waic)の計算が少し不安定になって、スコアがブレやすいという弱点がある。
              • LOO(正確にはPSIS-LOO): WAIC とほぼ同じ予測力を測る指標なんだけど、内部で「外れ値に対する警告システム(Pareto k 統計量)」が動いてくれるから、14サンプルみたいな少サンプルデータに対して、より安全で正確に機能する。
            # 各モデルのサンプリング結果を格納して、どの観測値の尤度で比較するかを変数名で指定する
            model_compare = az.compare({
                "t_dist Weakly Prior Model": trace_weakly,
                "t_dist Informative Prior Model": trace_informative,
                "t_dist Truncated Model": trace_truncated,
                "Gamma Weakly Prior Model": trace_gamma
                },
                var_name="obs_B",
                # ic="waic"  # デフォルトはloo
            )
            az.plot_compare(model_compare);
            
            
            model_compare
            

            表の見方

            • rank: どのモデルが優秀か。
              • 予測性能がいい順番。
            • elpd_loo(elpd_waic): 予測性能のトータルスコア。
              • 期待対数予測密度(対数予測密度の期待値 Expected Log Pointwise Predictive Density)。値が大きい、つまり0に近いほど予測性能が優秀。未来のデータをどれだけ精度よく予測できるかを表す。
              • t分布たちはほぼ互角だけど、ガンマ分布はかなり低いスコア。つまり「14サンプルの手元のデータに対しては、t分布のほうが圧倒的に座りが良かった」ということを意味している
            • p_loo(p_waic): 有効パラメータ数。
              • モデルの複雑さ(過学習のしやすさ、ペナルティの大きさ)を表す。
              • パラメータ数が多かったり、観測データに無理やり形を合わせよう(過剰適合)とすると、この数値が大きくなりelpdが減点される仕組み。
              • t分布勢に対してガンマ分布は小さい。ガンマ分布モデルは無駄な複雑さがなく、シンプルにデータを表現していることを示している
            • elpd_diff: 1位との予測スコアの差分。
              • 差が4以上あると有意な差とみなされることが多い
              • t分布たちの差分は微量なので1位とほぼ同等と言える。ガンマ分布はずいぶん離れており、今回データにおいては予測力不足と言える。
            • weight: 予測ブレンドの重み付け
              • もしこれらのモデルを合体させて未来を予測するなら、どのモデルの意見を何割信じるべき?というブレンド比率(0〜1)。
              • LOOの場合(内部ではスタッキング法という技術が使われることが多い)、モデルの実力が伯仲していたときに0.6と0.4みたいに綺麗に分散して出力されやすい(複数モデルの予測パワーのバランスをリアルに反映しやすい。重み付けの計算がより安定的になる)
              • WAICの場合は微差であっても1位のモデルに 1.0(100%)と極端に全振りされやすい。
            • se: トータルスコアの標準誤差
              • 各モデルのelpd_loo(elpd_waic)が、サンプリングのブレによってどれくらいバラつく可能性があるかを表す不確実性の幅(標準誤差)。
            • dse: 差分の標準誤差(elpd_diff自体の標準誤差)。
              • elpd_diff ÷ dseの計算結果が2を超えているかどうかが、実務上の超重要ラインになる。
              • 2未満であれば、1位のモデルと数理的には完全に互角・誤差の範囲内。
              • ガンマ分布は2を大きく超えており、ガンマ分布が負けているのはサンプリングの偶然ではなく明確に実力差であると言い切れる。
            • warning: 計算が破綻していないかの警告
              • データの中にLOO(WAIC)の前提を揺るがすような過度なばらつき(極端な値)があり、指標の計算が数理的に変になってないかのフラグ。
              • True だと数値が信用できない、False だと健康に計算できたという意味。
              • LOOのwarning=Trueは、
                • 内部で パレートk統計量(Pareto k diagnostics)という厳密なデバッグシステムが動いて警告を出す。
                • データ1件1件に対して、このデータはモデルにとって予測しづらい外れ値になってないか?を全件チェックして、基準値(k>0.7)を超えたデータが1件でもあるとwarning=Trueになる。
              • WAICのwarningは、
                • データ全体のバラつきをなんとなく見て、なんか破綻してそうってアバウトに警告を出すだけ。
                • WAICではt分布勢はサンプルの少なさや裾の厚さのせいでTrueだが、ガンマ分布モデルは Falseだった。
                • ガンマ分布は非負のデータ構造を数理的に正しく捉えているから、警告を出さずにものすごく健康に計算できたという、ガンマ分布の構造的な美しさが証明されている。
            • scale: 計算の単位空間。
              • 対数尤度をどのスケールで計算したか。ArviZでは一律でlog(対数空間)が使われる

            モデル評価

            • 4モデルの中ではTruncated Modelが最も予測能力が高いと評価された(僅差のためサンプリング次第でTOP3の並びは変わる可能性あり)
            • t分布の3モデルはほぼ同程度に対し、ガンマ分布モデルは予測能力が劣ると評価された
            • ガンマ分布モデルは微量ながらdivergenceが発生していた。また94%HDIの幅が広すぎる推定だった
            • 以上からすると、ガンマ分布モデルを採用するのはなさそう。t分布についてはどれを採用してもよさそうとの結論

            2020年4月11日土曜日

            ブランディングの科学

            『How Brands Grow : What Marketers Don't Know』バイロン・シャープ

             
            ✅ 3行まとめ
            • ブランドの成長には、購入者数の拡大が重要である
            • 特に消費者の大多数を占めるライト/ノンユーザーへのアプローチが欠かせない
            • ブランドの独自性を追求してブランドを識別しやすくすることが購入につながり、ブランドを成長させる
            ⚠️ 背景事情
            • 人間の脳は注意力散漫でスルースキルが高い。顕著な手がかりがないブランドや広告は存在しないも同然。
            • 人間の記憶は不確かで不安定である。明瞭で一貫したマーケティングによる記憶強化が購入を後押しする。
            • 消費者が購買行動時に非合理な選択をするのは珍しくない。新規獲得による購入者数拡大なくしてブランドは成長しない。

            概要

            マーケティング界では常識のように語られている法則や理論の中には、実はなんの裏付けもなかったり、誇大表現がまかり通っているものがある。

            著者バイロン・シャープ Byron Sharpは、従来のマーケティング理論をやみくもに盲信するのではなく、エビデンスに基づいたマーケティングを提唱。実際の販売データや市場調査データの裏付けとともに新たな法則・理論を提示しながら、より効率的なマーケティング活動をおこなうことの重要性を説く。

            エビデンスに欠ける従来思想に固執して出血大サービスのマーケティングを続けるのか、それともデータで検証された確からしい見識を携えてブランドを有意義に成長させるのか。見なかったフリをして進化を止めるのか、それとも積極的に取り込んで自らをも成長させるのか。後者でいたい方には有益な書籍。




            Ch1. エビデンスに基づいたマーケティング

            Evidence-based Marketing

            • マーケティングの教科書に書かれた理論の大半は、エビデンスの記述がない
            • マーケティングの歴史は浅いため、表層的な印象や根拠なき言い伝えに頼っている面がある
            • 誤った仮説を立てるから、方向を見誤ってしまう

            Ch2. ブランドはどのように成長するか

            How Brands Grow

            • 小規模ブランドは、大規模ブランドよりも購入者数がはるかに少ない
            • 小規模ブランドは購入頻度も少ない、これらを合わせて「二重苦の法則」と呼ぶ
            • ブランドの成長には購入者数の拡大が重要である

            Ch3. 顧客基盤を拡大させる

            How to Grow Your Customer Base

            • 「1:5の法則」「5:25の法則」を裏付けるデータはない
            • 顧客離反率をゼロに抑えられたとしても、ブランド成長度はたかが知れている
            • 新規顧客獲得に成功するとブランドは成長し、失敗すると衰退する

            Ch4. ブランドにとってもっとも重要や顧客を探す

            Which Customers Matter Most?

            • ヘビーユーザーはありがたい、だが習慣化した購買行動を変えるのは難しい
            • 2割のヘビーユーザーが売上に占める割合はせいぜい6割である
            • ライトユーザーは、ブランドの大きな売上、大きな成長をもたらす可能性を秘めている

            Ch5. 顧客のパーソナリティプロファイルを知る

            Our Buyers Are Different

            • 自社ブランド顧客と競合ブランド顧客の属性は似通っている
            • 競合ブランドの現顧客は、自社ブランドの将来顧客になる可能性がある
            • 各ブランドの購入者は別人ではあっても、属性が異なるわけではない

            Ch.6 真の競合ブランドを探す

            Who Do You Really Compete With?

            • 各ブランドは顧客を共有している、各ブランドの顧客はセグメントされていない
            • どのブランドも、大規模ブランドとの顧客重複率は高く、小規模ブランドとの顧客重複率は低い
            • 市場には高品質/高価格帯のような境界線は存在するが、完全に分断された市場とは捉えない方がよい

            Ch7. 消費者のコミットメントを知る

            Passionate Consumer Commitment

            • ブランドの購入体験がブランド選好を高め、ロイヤルティにつながる
            • 大規模ブランドほどライトユーザー比率が高いがために、ロイヤルティも高く見える
            • ブランドの熱狂的信者は確かに存在するが、マーケティング的な重要性は低い

            Ch8. 差別化か、それとも独自性か

            Differentiation versus Distinctiveness

            • 差別化は長続きしない、差別化よりも独自性を追い求めるべきである
            • 消費者はブランド間の差異に気づいてはいる、だがお気に入りブランドの購入を止めるほどではない
            • 独自のブランド資産は、消費者のブランドへの気づきやすさ、想起しやすさ、購入促進につながる

            Ch9. 広告の機能

            How Advertising Really Works

            • 広告は売上に寄与している、ただしすぐ売上に効くことも、止めて売上がすぐ落ち込むこともほぼない
            • 広告は以前の記憶を思い起こさせたり、時に記憶に刷り込まれることで機能する
            • 広告は独創的な内容によって、ブランドの独自性を維持、構築する

            Ch10. 価格販促の役割

            What Price Promotions Really Do

            • 価格販促はすぐ売上に効く、だが長続きしないし、非常に大きな犠牲をともなう
            • 価格販促で新規獲得はできない、購入者の大半はそのブランドの過去購入経験あり
            • 消費者は幅広い価格帯から商品を選んでいる、低価格志向者だけを狙った価格販促は困難である

            Ch11. ロイヤルティプログラムが失敗する理由

            Why Loyalty Programs Don't Work

            • ロイヤルティプログラムの効果は少しはある、だが利益やブランド成長への寄与はないに等しい
            • 大多数を占めるライトユーザーは低購入頻度なぶんプログラム参加可能性が低く、効き目も薄い
            • ヘビーユーザーはプログラムに参加しても購買行動に変化はない、つまり多額の投資に見合わない

            Ch12. メンタル・アベイラビリティとフィジカル・アベイラビリティ

            Mental and Physical Availability

            • 消費者は限られたお気に入りブランドを購入しがち、そもそも大半のブランドは眼中にない
            • ブランドを想起してくれる人数と、購入候補に加えてもらえる回数、この2点を増やす努力を
            • ブランドの配荷率と店頭での目立ちやすさを確保する、これが購入を後押しする

            Ch13. 最後に一言

            A Final Word

            • 7つのシンプルなマーケティングの法則
            1. ブランドのサービス/製品カテゴリー内のすべての消費者に、配荷およびマーケティングコミュニケーションの両面から継続的にリーチする
            2. ブランドの買い求めやすさを確保する
            3. 目立つ。その過程を誤るとブランドコミュニケーションに費やす費用が無駄になる
            4. ブランドが目立ち、買いやすくなるためにも、ブランド記憶の構造を構築/刷新する
            5. 独自のコミュニケーション資産を創造する
            6. 一貫性を保ちながら、新鮮さと興味を失わない
            7. 競合力を維持しつつ、多くの人に受け入れられる。ブランドを買わない理由を与えてはならない

            ブランドが成長することは可能だ。新しいブランドである必要はない。優れた広告、優れたブランディング、優れたメディア戦略、優れた店内ディスプレイ、そして前述の7つのルールに従うこと、これらすべてが成長への道だ。

            本書に登場した法則

            • ダブルジョパディの法則 Ch2.
            • リテンションダブルジョパディの法則 Ch3.
            • パレートの法則(60/20) Ch4.
            • 購買行動適正化の法則 Ch4.
            • 自然独占の法則 Ch7.
            • 顧客基盤が類似する Ch5.
            • ブランドに対する態度と思いが行動ロイヤルティに反映される Ch7.
            • ブランド使用体験が消費者の態度に影響を与える Ch5.
            • プロトタイプの法則 Ch8.
            • 購買重複の法則 Ch6.
            • NBDディリクレ Ch4.

            関連情報