牛の一歩も、一歩は一歩

日々の関心、備忘録などをまとめる.

python 小技

意外と便利な小技をまとめる. 一般的なものから, まあ使わんものまで, 見つけたものを追記していく予定.

数値計算

floatの値の小数第一位が0かどうか判定

  • float型の変数の整数判定
  • 以下で判定. 返り値はboolean
値.is_integer()

階乗

import math
math.factorial(x)

累乗

  • a**n
pow(a, n)

dictionary

keyが存在しない場合のみ初期化

dictionary.setdefault(key, value)

文字列

listの文字列化

  • code
'_'.join(["hoge", "fuga"])
  • output
hoge_fuga

IO

listのunpack

  • code
list_=[a,b,c,d]
print(*lilst_)
  • output
a b c d

systemdのstart request repeated too quickly

環境

  • debian10

内容

あるミドルウェアを新しくaptでサーバに導入し, 起動し, 状態の確認systemctl status *としたところ, start request repeated too quicklyがエラー文として表示された. 調べてみたところ, どうやらユニットの起動に失敗した際に, 自動でユニットの再起動が行われるように設定されているようで, その再起動のスパンが早すぎるために出てくるエラー文らしい. つまり正しいエラー文が, 再起動のせいで埋もれている. 再起動のスパンを長くする手立てもあるが, とりあえずの処置として, そもそも起動に失敗した際に, 再起動しないように設定を行った.(いずれ再起動のスパンを長くする方法も調べる)

起動に失敗した際に再起動しないように設定

  • /lib/systemd/system/*.serviceの一部を書き換え
Restart=no
  • 設定の更新と起動
systemctl daemon-reload
systemctl start *

マイクロサービスアーキテクチャ chapter1

マイクロサービスアーキテクチャのchapter1のメモ

1章

マイクロサービス

思想

  • 最低限のサービスごとにコードを分けようという思想

    • 分割の際に凝集性に着目して分割
      • 凝集性は、端的に言えば、変更する理由が同じものは集める、それ以外は分割するという考え
    • どこまで分割するかが肝
  • 単一のコードでサービスを運用する場合

    • 技術の置き換えが大規模で大変
      • コードのどこを修正すべきかわかりにくい
      • バグの修正や実装が大変

自律性

  • 本書では、クラウド、オンプレのどちらかは考慮しない
  • サービスはAPIにより、通信して、動作
  • それぞれのサービスが独立して稼働, 変更もそれぞれ別個に可能

利点

技術特質性

  • マイクロサービスでは、サービスごとに異なった、それぞれのサービスに最も適したツールの選択が可能
  • 新たな技術の取り入れが容易
    • モノリシックなサービスと異なり、影響箇所が少ない

回復性

  • 一部に障害が生じても、その部分を切り捨て、残りで継続可能

スケーリング

  • マイクロサービスでは、各サービスごとにスケーリングを行うことが可能であり、無駄が少ない

    • i.e.) 大きなサービスのみ高価なハードウェアで、その他は安価なハードウェアで動作などが可能
  • tips

    • スケーリングとは
      • スケーリングとは、同じサービスを並列稼働し、LBなどでトラヒックの分散などを行うこと

デプロイ

  • デプロイのリスクを最小限に止めることが可能

開発チーム

  • サービスごとに小牙なチームによる開発が行えるため効率が良い

合成可能性

  • 一つのシステムが存在した際に、新たな利用方法(web, tablet app etc.)用の新たな機能を取り入れやすい
    • 携わったことがないのでいまいちモノリシックでは難しいのかがよくわからん

交換可能にするための最適化

サービス指向アーキテクチャ

  • サービス指向アーキテクチャ(SOA)

    • 複数のサービスを連携させて一つのサービスを提供する構成
    • 別デーモン
    • サービス同士のやりとりは、ネットワークを介して行う
  • tips

マイクロサービスに類似した思想、技術

  • tips
    • ライブラリとモジュールの違い
      • ライブラリ モジュールで検索すると、まともそうなURLのサイトは出てこなかったが、概ね以下の通りっぽい
      • モジュールはスクリプトそのもの
      • ライブラリはモジュールの集合体

共有ライブラリ

  • コードを目的ごとに対応した複数のライブラリに分割
  • 利点
    • ライブラリごとにチームを作って開発を行うことが可能
  • 欠点
    • 同じプラットフォームで動作させなくてはならない(同じ開発環境?verの統一等のことか?)
    • システムの各部を独立してスケーリングできない
    • 新たなライブラリをデプロイする場合、全てデプロイし直さなければならない
  • 組織内で用いる分には問題ないが、サービスのためのシステムで取り扱う場合は注意が必要

モジュール

  • コードを目的ごとに対応した複数のモジュール(スクリプト)に分割
  • 実行中のプロセスにも、プロセスを止めずにモジュールのデプロイが可能

欠点

  • 分散システムで新たな問題が生じることが多々ある

統計的因果探索 chapter1~3

1章 統計的因果推論

  • 統計的因果推論とは、相関があるだけでなく、実際に変化した時に、目的変数がどうなるかを推測する

    • この書籍では、統計的因果推論の一種である統計的因果探索を解説
  • 相関はあくまで、データから読み取れる結果でしかなく、因果関係は考慮していない

i.e.
- チョコの消費量が多いと、ノーベル賞受賞者が多い
=>相関

- チョコの消費量を増やしたときにノーベル賞受賞者数がどうなるか
=>因果関係
  • 因果関係は、因果グラフで表す
    • ノード
      • 観測変数&未観測変数
    • 有向エッジ
      • 因果関係の有無
        • エッジに因果関係の強さといったラベルは存在しない
        • エッジの向きで、原因=>結果
  • 矢印の間に挟まれるノードを共通原因と呼ぶ
    • 共通原因のうち、未観測なものを未観測共通変数と呼ぶ
  • 因果関係はないが、相関がある場合、擬似相関と呼ぶ

  • 未観測、観測変数の値より、ある変数の値が生成される工程を生成過程と呼ぶ

    • x, yからzが生成されている際、z=f(x, y, e)で表され、eは誤差関数と呼ばれ、バイアスのような役割をする
      • 未観測変数とバイアスは、なんらかの確率分布に従うと考え、確率変数で表す
  • 相関係数では、因果関係の大きさを測ることはできない

2章 統計的因果推論の基礎

統計的因果推論は因果グラフが既知の場合の手法

  • 実質科学
    • 因果関係を明らかにする目的の科学
  • 方法論

反事実モデル

  • 個体レベルの因果
    • 個体に対して二種類以上の試行を行い、因果関係があるかを実験
    • この個体が属する集合が存在した場合、その集合全体に、個体の因果関係が同様に適用可能かはわからない
  • 集団レベルの因果
    • 集団に対して二種類以上の試行を行い、集団の何割がどのような結果になるか観測

構造方程式モデルによるデータ生成過程の記述

  • 構造方程式
    • データの生成過程を定式化
    • yというデータが生成される過程は以下
      • xは観測変数
        • xもyと同様に未観測の誤差変数から生成されていると考えられる
      • eは未観測変数&誤差変数
      • x, yの誤差変数らは独立とは限らない
y=f(x, e)
  • yは内生変数
    • 構造方程式によって記述される変数
    • いくつかの変数で説明される変数
  • 誤差変数eは外生変数
    • 構造方程式において、生成手順が語られない変数

構造的因果モデル

反事実モデルと構造方程式を組み合わせたモデル

  • 集団レベルの因果構造方程式モデルによって記述
    • 介入により、ある変数に対して、任意の定数を代入
      • 集団に対する試行を、モデルを作成する人間が指定
      • i.e.) 薬を飲む、飲まないetc.
    • x=cという介入do(x=c)をした時、yの確率分布はp(y|do(x=c))で表される
  • 介入後の分布が介入前と異なる場合, 介入した変数xとyの間に因果関係があると言える
  • 個体レベルも同様に介入によってどう値が変化するかで分析可能
  • 因果効果の大きさの定量
    • 平均因果効果で因果効果の大きさを定量
      • 二種類の介入を行った分布の期待値の差
  • 出来事の説明
    • 観測された結果より, 過去に何があったかを説明
    • 潜在反応モデルにより深い考察が可能

ランダム化実験

  • 変数の値を, 個人ごとにランダムな値に
    • 未観測変数を独立に
      • 時系列的に捉えることで, 未観測共通原因をなくす

3章 統計的因果探索の基礎

統計的因果探索は因果グラフが未知の場合の手法

現実問題として取り扱う場合、統計的因果探索して因果グラフの推測を行ったのちに、統計的因果推論により、その因果関係の大きさなどを推測することも多々ある

本書では、ランダム化実験を行わず、いくつかの制約を設けることで因果グラフを推測する手法を取り扱う

統計的因果探索

  • 統計的因果探索は観測されたデータx, yより, 因果グラフを推測する問題
    • xとyに因果関係があるかどうか
    • 外生変数がどのような分布に従うか
      • ノンパラメトリック
        • 分布、関数になんの仮定も置かない
        • 因果関係が一方向であるという仮定を置く
        • データから読み取れることのみから因果グラフを推測するためシンプル
        • ただし、いくつかの因果グラフの候補をモデリングできるが、どれが優れているか評価できない
      • パラメトリック
        • 分布、関数に仮定を置く
        • モデルの単純化、数値解析の簡易化
      • セミパラメトリック
        • 関数に仮定を置き、分布には仮定を置かない
        • 関数系に線形性、分布に非ガウス分布を採用するモデルをLiNGAM (Linear Non Gaussian Model)と呼ぶ
  • 識別可能性
    • 因果グラフが識別可能であるかどうか(=観測データから因果グラフが一意に定まるかどうか
    • 因果グラフの構造が異なれば、観測変数の分布が必ず異なる場合、識別可能
  • 仮定によって、因果グラフの候補群の数を減らすことが可能
    • 誤差変数が独立である仮定
    • 非巡回グラフである仮定
      • 非巡回を仮定することで、先祖、親、子孫などの概念を導入可能
  • 平均因果効果
    • {x1, ..., xn}の因果グラフがある場合、x1とxkの因果効果は
      • x1からxkとの有向エッジがある場合、直接効果をcalc
      • x1からxkまで、どこかノード (中間変数)を経由したエッジが存在する場合、message passingの要領で、間接効果をcalc
      • 直接、間接効果の和が、平均総合効果

ノンパラメトリック

  • 二種類の仮定を置く
    • 因果的マルコフ条件を導入
      • 変数それぞれを親に当たる変数で条件付けするとその非子孫の変数と独立になる(親、先祖を含む
    • 忠実性を導入
      • 因果グラフを見ると従属なはずなのに、実際には独立ということがないように
      • 独立性は、因果グラフの構造からのみ表されるという仮定
  • (おそらく二変数に着目して)、同じ条件付き独立性を有する因果グラフを持つモデルの集合をマルコフ同値類と呼ぶ
  • ノンパラメトリックな手法では、マルコフ同値類への絞り込み等を行うことは可能だが、一意に因果グラフを特定できない
    • 制約に基づくアプローチ
      • 条件付き独立性を試薬として、それを満たすような因果グラフを探索
    • スコアに基づくアプローチ
      • マルコフ同値類ごとにスコアを出し、良いものを選択

パラメトリック

  • ノンパラメトリックと比較して、識別可能性は向上しない
  • ノンパラメトリックと同様に、マルコフ同値類内の全ての期待値を計算し、最小or最大の値によって評価
    • 少なくとも、期待値が正なので因果関係がありそう等

セミパラメトリック

  • 誤差変数の分布に、非正規分布を仮定することで、識別可能性が向上するらしい

pythonのicecreamを調べてみた

icecream

ideをどうしても使いたくない、logging, printでデバッグしたいという頑固ものにうってつけのパッケージ。 というかそういう層以外に、需要なさげ。 以下、readmeの簡単なまとめと個人的な意見をまとめる。

内容のverは2.0.0。git hubはhttps://github.com/gruns/icecream

TL;DR

  • インタラクティブでは使えない
  • printの代わりにicecreamを使うと変数名と変数の値が出力される
  • 関数内の条件分岐のデバッグ簡単
  • icecreamによる出力を一括で有効,無効化できる
  • main scriptでicecreamのメソッドを実行するだけで、同プロジェクト内のスクリプトでもicが使える(2021年1月20日; ver2.0.0;ではpythonのver次第で実行できない)

インタラクティブ

試してみようかと思ってインタラクティブでやってみたが使えなかった。スクリプトを書く前提<-まあ困らん

>>> from icecream import ic
>>> a=None
>>> print(a)
None
>>> ic(a)
ic| Error: Failed to access the underlying source code for analysis. Was ic() invoked in an interpreter (e.g. python -i), a frozen application (e.g. packaged with PyInstaller), or did the underlying source code change during execution?

printの代用

icecreamを,使うことで、変数の値のprintと同時に、変数名まで表示。デバッグで数値とその数値がどの変数のものかをわざわざprint文で書いたり、関数化する手間を省いてくれる点は便利。

from icecream import ic

a="hoge"
ic(a)
ic| a: 'hoge'

パッケージの中身を全く見てないので確証はないが、どうやらicの括弧内のテキスト情報を読み込んで,表示しているだけのようなので、関数、無名関数、リストでも同様に表示される。

  • 普通の関数
from icecream import ic

def hoge(a):
    return "hoge"
a=None
ic(hoge(a))
ic| hoge(a): 'hoge'
  • 無名関数
from icecream import ic

hoge=lambda a: "hoge"
a=None
ic(hoge(a))
ic| hoge(a): 'hoge'
  • リスト
from icecream import ic

hoge=["hoge", "fuga"]
ic(hoge[0])
ic(hoge)
ic| hoge[0]: 'hoge'
ic| hoge: ['hoge', 'fuga']
  • attribute
from icecream import ic
class Hoge():
    a="hoge"
hoge=Hoge()
ic(hoge.a)
ic| hoge.a: 'hoge'

分岐に入っているか、どこまで動作したかの確認

ide使いたくない、Debugger使うより…ry の民は、基本的に条件に正しく入っているかどうかやエラーで止まった際、どこまで正しく動作していたのかをprintを使って確認しがち(俺だけか?). プログラムの至る所にprint("hoge1"), print("hoge2"), ...と現在プログラムのどこにいるのかわかる様に連番でprintしてゆく手間を軽減

なお動作するのは、関数内のみの模様なので、簡単な単体テストのときなどに用いると、便利そう

from icecream import ic
def hoge(a):
    ic()
    if a:
        ic()
    else:
        ic()
    print("\n")
hoge(0)
hoge(1)
ic| tmp.py:3 in hoge() at 04:30:44.835
ic| tmp.py:7 in hoge() at 04:30:44.836

ic| tmp.py:3 in hoge() at 04:30:44.837
ic| tmp.py:5 in hoge() at 04:30:44.838

icの無効化

一括で、あるコード以降のicによる出力を停止。再開も可能。正直、使い道が、プログラムが完成した際に書かれているテスト用のprintを消す手間の軽減ぐらいしか思いつかない。どっちにしてもprintしかりicしかり、残ってるとコード的に美しくないので, 本番環境のコードに残っているのは個人的にはどうかと思う。趣味で、誰にも見せる予定のないコードとかだったりあり。

from icecream import ic
ic(1)

ic.disable()
ic(2)

ic.enable()
ic(3)
ic| 1
ic| 3

importの手間が少ない

https://github.com/gruns/icecream/issues/51で報告されているように, 2021年1月20日; ver2.0.0;現在ではpipでインストールした場合, pythonのverが3.7.3だと利用できなかった. 3.8.1に変更した際, 利用できたので, pythonのverをあげる必要がある. プロジェクトによってはpython 3.7.*を使わざるを得ないことも多々あるので, どうにしかほしい.

project
  ├  main.py
  └  hoge.py
  • main.py
from icecream import install
install()
      
import hoge
hoge.hoge()
def hoge():        
    a="hoge"
    ic(a)

git commit, add取り消し

脳死git add .からのgit commit -m "fixed"をした後に, 余計なファイルをcommitしていることに気づくことがままあり, その修正方法を毎回ググるのが面倒なのでまとめる.

直前のcommitの取り消し

  1. git logでcommitされてしまっていることを確認して後悔
  2. git reset --soft HEAD^で作業ディレクトリ内の内容に変更を加えず, 直前のcommitを取り消し.
  3. git logで直前のcommitが取り消されていることを確認.

直前のadd取り消し

  1. git statusで余計なファイルがaddされてしまっていることを確認
  2. git resetで作業ディレクトリ内の内容に変更を加えず, 直前のaddを取り消し
  3. git statusで, addが取り消されていることを確認

binary indexed treeのpython実装

AtCoder Library Practice Contest - AtCoderでbinary indexed treeなるものを知ったため, http://hos.ac/slides/20140319_bit.pdf: titleを元に実装(ほとんどまるパクリ). 以下コード.

class BinaryIndexedTree():
    """
    各関数のaは全て引数の値になっている前提.(0~n-1)
    Attributes:
        n: データ数
        data: データ
    """
    def __init__(self, n, data=None):
        self.n=n
        self.data=[0 for _ in range(n)]
        if not data is None:
            for i, a in enumerate(data):
                self.add(i, a)

    def add(self, a, w):
        x=a
        while x<self.n:
            self.data[x]+=w
            x=x|(x+1)

    def sum(self, a):
        if a<0:
            return 0
        ret=0
        x=a
        while x>=0:
            ret+=self.data[x]
            x=(x&(x+1))-1
        return ret