雑記
参考文献: client_python/metrics.py at master · prometheus/client_python · GitHub
あなたは弁当販売を始めることにしました。A か B の type を指定してリクエストしてもらい、それに応じてA弁当(バターチキンカレー)かB弁当(ローストビーフ)を渡したいと思います。以下のようにすれば、localhost:8080/bentou?type=A にアクセスするとバターチキンカレーが返却されます。
import asyncio from aiohttp import web class BentouHandler: async def handle(self, request): params = {k: v for k, v in request.query.items() if v} if 'type' not in params: raise ValueError('type がありません') type_ = params['type'] bentou = None if type_ == 'A': await asyncio.sleep(2) bentou = {'主食': 'ナン', 'おかず': 'バターチキンカレー'} elif type_ == 'B': await asyncio.sleep(1) bentou = {'主食': 'ごはん', 'おかず': 'ローストビーフ'} else: raise ValueError('type が不正です') return web.json_response(bentou, status=200) handler = BentouHandler() app = web.Application() app.add_routes([web.get(f'/bentou', handler.handle)]) if __name__ == '__main__': web.run_app(app, port=8080)
import asyncio from aiohttp import web from prometheus_client import Counter, Histogram, generate_latest class BentouHandler: async def handle(self, request): params = {k: v for k, v in request.query.items() if v} if 'type' not in params: raise ValueError('type がありません') type_ = params['type'] bentou = None if type_ == 'A': await asyncio.sleep(2) bentou = {'主食': 'ナン', 'おかず': 'バターチキンカレー'} elif type_ == 'B': await asyncio.sleep(1) bentou = {'主食': 'ごはん', 'おかず': 'ローストビーフ'} else: raise ValueError('type が不正です') return web.json_response(bentou, status=200) class BentouMetrics: def __init__(self): # 必要なカウンタを用意 self.get_req_counter = Counter('get_request_count', 'リクエスト数') self.resp_time_hist = Histogram('resp_time_hist', 'レスポンスタイム', buckets=[0.5, 1.5, 2.5]) @web.middleware async def wrapper(self, request, handler): # ハンドラをラップして各種メトリクスを計測する # 目的のエンドポイント以外へのリクエストは計測対象外 if request.path not in ['/bentou']: return await handler(request) # 各種メトリクスを計測する self.get_req_counter.inc() # リクエスト数をインクリメント with self.resp_time_hist.time(): # レスポンス時間を計測 response = await handler(request) return response async def exposer(self, request): # 現在のメトリクスを返却する return web.Response(body=generate_latest(), content_type='text/plain') @classmethod def setup(cls, app): metrics = cls() app.middlewares.append(metrics.wrapper) app.router.add_get('/metrics', metrics.exposer) handler = BentouHandler() app = web.Application() BentouMetrics.setup(app) app.add_routes([web.get(f'/bentou', handler.handle)])
... # HELP get_request_count_total リクエスト数 # TYPE get_request_count_total counter get_request_count_total 2.0 # HELP resp_time_hist レスポンスタイム # TYPE resp_time_hist histogram resp_time_hist_bucket{le="0.5"} 0.0 resp_time_hist_bucket{le="1.5"} 1.0 resp_time_hist_bucket{le="2.5"} 2.0 resp_time_hist_bucket{le="+Inf"} 2.0 ...
import time class BentouMetrics: def __init__(self): # 必要なカウンタを用意 self.get_req_counter = Counter('get_request_count', '正常に返せたリクエスト数') self.get_err_req_counter = Counter('get_error_request_count', '正常に返せなかったリクエスト数') self.resp_time_hist = Histogram('resp_time_hist', '正常レスポンスタイム', buckets=[0.5, 1.5, 2.5]) @web.middleware async def wrapper(self, request, handler): # ハンドラをラップして各種メトリクスを計測する # 目的のエンドポイント以外へのリクエストは計測対象外 if request.path not in ['/bentou']: return await handler(request) # 各種メトリクスを計測する time_0 = time.perf_counter() try: response = await handler(request) self.get_req_counter.inc() # リクエスト数をインクリメント self.resp_time_hist.observe(time.perf_counter() - time_0) # レスポンス時間を記録 except Exception as e: self.get_err_req_counter.inc() # 正常に返せなかったリクエスト数をインクリメント raise e return response
雑記: 分布収束関連の話
お気付きの点がありましたらご指摘いただけますと幸いです。
- Amazon | Asymptotic Statistics (Cambridge Series in Statistical and Probabilistic Mathematics, Series Number 3) | van der Vaart, A. W. | Applied
- 本記事はこの 11~12 ページの内容に尾ひれを付けたものである。筆者の誤りは筆者に帰属する。
- 雑記 - クッキーの日記( 参考文献 [1] の全体図があるだけ )
- 雑記: t分布の話 - クッキーの日記( 母分布が正規分布の場合の t 統計量の話 )
まとめ
|
統計量の漸近分布(+ α )
統計量とは以下のような、確率変数の関数になっているような確率変数でしたよね。分母の はいわゆる不偏分散です。母分布の分散 ではないことに留意してください。
では、「同一の分布」が正規分布ではない場合はどうだろう。
うん。だから、 がとても大きいときを考えてみよう。「 が大きいときは正規分布に近づく」というような定理があったよね?
そうだね。ここで、いまは であるということしよう。それで、後々の都合上、以下の2つの定理をつかって、 が何にどんな収束をするかを考えてみてほしい。
とするのですか? そして誘導が強い……まずは [関連記事 イ] と同様に を展開しましょう。
ここまでをまとめると以下です。
- 独立に同一の分布(平均 ,分散 )にしたがう に対する 統計量について以下のことがいえる。
- 分子の は に分布収束する。
- 分母の は に確率収束する。
ここまできたら以下の補題を適用することができるよ。
はあ……うーん、あの、基礎的な統計学で信頼区間を求めたり、統計的仮説検定をしたりするときは、「この統計量はこの分布にしたがう」がきちんと求まっていましたよね? 対していまわかっているのは、「この統計量はこの分布に『分布収束する』」です。もちろん分布収束するのであれば観測をたくさん重ねていけばその分布に近づきはするでしょうが……しかし、確か分布収束の定義は「分布関数の『各点』が収束すればよい」といったものでしたよね? それだと、観測をある程度たくさん重ねたとき、統計量の分布が収束先の分布に近い形をしている保証はないのではないですか? 各点収束だったら、「こちらのエリアではもう収束先の分布に近いですが、あちらのエリアはまだまだ近くないですね」ということもあり得るでしょう? そのような状況かもしれないのに信頼区間を議論するのは乱暴なのでは?
実際そういう心配はあるかもね。ただ、ここまでの例については一応、分布関数は一様収束しているけどね。
あれ、そうなんですか?
収束先が連続分布であるときの分布収束
連続分布なら以下が成り立つので示してみよう( [関連記事 1] の12ページ)。
以下のように示せますね……確かに連続分布であれば一様収束します(2022-11-14 追記: 以下の手書きノートでは1次元の場合も2次元の場合も「N'=* をとって、k=* とすれば、」とありますが、N' は k に依存するので「k=* として、N'=* をとれば、」が正しいです)。