ryuiso2のブログ

ryuiso2のブログ

自分用のメモです。

スペイン風オムレツ (トルティージャ)

下ごしらえ

じゃがいも

  1. じゃがいもを洗う
  2. 電子レンジでチンする(根菜モード)
  3. 皮を剥いて1cm四方に切る

ハム

  1. 1cm四方に切る

玉ねぎ

  1. 1cm四方に切る

  1. 卵を2n個割ってボウルに移す(nは食べる人数)
  2. 卵をとく(白身を切るイメージ、空気を含ませる)
  3. 塩、バジル、胡椒を適当に入れる(塩以外は多めでOK)

調理

  1. フライパンにオリーブオイルを敷く
  2. 玉ねぎ、ハムを入れて少し炒める
  3. オリーブオイルをフライパンの周りに追加する
  4. 卵を一気に流し込む
  5. フライパンの周りに張り付かないように菜箸で混ぜる
  6. 固まってきたらフライパンの上に大きなお皿を重ね、お皿にひっくり返す
  7. ひっくり返した卵をフライパンに戻して裏側を焼く
  8. 適当なタイミングで火を切り、完成

その他

  • じゃがいもが入っていればスペイン風らしい

北海道

登別

帯広

元祖豚丼のぱんちょう

  • 帯広名物の豚丼
  • 多数有名店があるが、ここも随一の人気店
  • 炭火で焼かれた豚の味と香りは格別

f:id:ryuiso2:20200226224831j:plain
元祖豚丼のぱんちょう。炭火で焼いてくれる。

f:id:ryuiso2:20200226225101j:plain
ぱんちょうの行列。

釧路

釧路湿原

  • 雨の日に行ったので何も見えませんでした。
  • 天気は運です。いつかリベンジしたい。

シャケ番茶

f:id:ryuiso2:20200226230207j:plain
シャケ番屋の炉端焼き。シャケは油がしっかり乗っていてとても美味しい。

  • 朝ごはんにいきました。
  • ご飯がついてくるのが嬉しい。
  • お店の人が焼き加減を見てくれるのでありがたい。
  • 魚は個体を自分で選べるのも楽しいところ。

羅臼

知床食堂道の駅

f:id:ryuiso2:20200226231129j:plain
黒ハモ。油がかなり乗っている。

f:id:ryuiso2:20200226231317j:plain
北海道で食べるウニは格別。

  • 羅臼名物の黒鱧をいただきました。
  • ウニ丼も食べました。
  • 売店も充実しています。以下を購入。
    • トド肉の缶詰
    • 青いビール

知床峠

f:id:ryuiso2:20200226231330j:plain

知床峠。風がかなり強いが絶景。北方領土が見える。

  • 5月でも雪が見えており、スキーもできるらしい。
  • 車で行く際には雪にお気をつけください。
  • とにかく景色が良かったです。

網走監獄

f:id:ryuiso2:20200226232622j:plain
網走監獄入り口。アクセスが悪いにも関わらず多くの観光客で賑わっていた。

  • 近くの川を渡ったところに「本物の」刑務所があるので間違わないように注意。
  • 中は広く、展示物も多いのでかなり長時間楽しむことができます。
  • 筆者は時間都合で1時間強で出ましたが、まだまだ見たかったといった印象です。

旭川

旭川ラーメン「味特」

f:id:ryuiso2:20200226233722j:plain
旭川ラーメン屋「味特」

  • 醤油ベースのラーメン
  • お好みでバターも

Creamery濃夢 Milk Bar

f:id:ryuiso2:20200226234107j:plain
Creamery濃夢 Milk Bar

  • 美味しい乳製品がいただけます。
  • 小さい店舗ですが、雰囲気の良い店員さんでした。

青い池

  • apple製品の壁紙にもなった有名な観光地です。
  • 池を見るだけですが、歩く量が多いの所要時間は40~50分をみておいた方が無難です。

札幌

スープカレー

f:id:ryuiso2:20210112233654j:plain
スープカレー屋さん "Treasure"。周辺にいくつか店舗がありましたが、どこも行列ですごく人気店です。

札幌ビール工場

無料で工場見学ができます。ビールも無料で2二杯くらい飲めます。

f:id:ryuiso2:20210113001553j:plain
5月ごろに行けば敷地内に桜が咲いていてきれいです。

f:id:ryuiso2:20210113001359j:plain
ビールが苦手な人もノンアルコールビールやジュースが飲めます。
f:id:ryuiso2:20210113001458j:plain
サーバーでいれたてのビールがいただけます。格別。

小樽

JR快速エアポート

札幌→小樽の移動は電車で移動しました。JRが通っており、40分前後で移動できます。移動中の景色もとても良いので、進行方向一番前にいるのが良いかもしれません。

食べたもの

  • 八角: 身がプリプリで絶品でした。ここでしか食べられないと思っています。
  • イカ: イカは噛みきりにくく、あまり好きではないのですがここで食べたイカは絶品でした。イカが好きな人も嫌いな人も食べるべきです。

f:id:ryuiso2:20210112234121j:plain
海沿いを走るJR快速エアポートは長めも最高です。
f:id:ryuiso2:20210112234401j:plain
あまり聞き慣れない魚ですが、「八角」(はっかく)という魚です。

f:id:ryuiso2:20210113000647j:plain
小樽駅の近くには飲食店と土産屋さんがたくさんあり、その中の一つ。丼の内容を選べるお店でした。

小樽運河クルーズ

船に乗って遊覧もできます。ガイドさんの説明を聞くと小樽の歴史など、勉強になります。

f:id:ryuiso2:20210113000905j:plain
船上からの景色。一時期スマホの壁紙にしていました。

Twitterの投稿数がポアソン分布に従うか調べる

はじめに

筆者のTwitterの投稿頻度が低いので、筆者のツイート頻度はポアソン分布に従っているのではないか?と考え、χ二乗検定で確認してみました。 その結果、two-part ポアソン分布に従っていることが確認できました。その手続とソースコード1の記録です。

ツイート数の取得

  1. PCからWEB版Twitterで、自分のアカウントにアクセス
  2. 「もっと見る」→アナリティクス→ツイートタブ→データをエクスポート→BY DAY を指定してダウンロード ダウンロード時は期間を指定可能(一ヶ月単位でしかダウンロードできない。4~5ヶ月程度取得可能)

分析

フォルダ構成

  • DIR_HOME
    • scripts
    • daily_data (ここにダウンロードしたデータを置く)
      • daily_tweet_activity_metrics_アカウント名_YYYYMMDD_YYYYMMDD_ja.csv

定数とmain関数

コメントとソースコードの通りで、特に説明することはありません。

import os
import glob
import numpy as np
import pandas as pd
import scipy.misc
import matplotlib.pyplot as plt

DIR_HOME = os.path.dirname(os.path.abspath(__file__)) + os.sep + '..'
DIR_DAILY_DATA = DIR_HOME + os.sep + 'daily_data'
COL_TWEET_COUNT = 'Tweets published'
MAX_TWEETS = 7


def main():
    # 月ごとにまとめられた日付ごとのツイートデータファイル名を取得
    filenames = glob.glob(DIR_DAILY_DATA + os.sep + '*.csv')
    # 一日ごとのツイート数を集計
    num_tweet_freq = read_daily_data(filenames)
    # ポアソン分布に従った場合の期待度数を算出
    expect_distribution = calc_poisson_distribution(num_tweet_freq)
    zero_expected_tweet_freq = calc_zero_inflated_poisson_distribution(
        num_tweet_freq)
    expected_tweet_freq = expect_distribution * np.sum(num_tweet_freq)

    # χ二乗検定
    poi_text = chi_square_test(num_tweet_freq, expected_tweet_freq)
    two_part_text = chi_square_test(num_tweet_freq, zero_expected_tweet_freq)

    text = '               Poisson: ' + poi_text + '\n' +\
        'Two-part Poisson: ' + two_part_text
    # ヒストグラムの可視化
    draw_hist(num_tweet_freq, expected_tweet_freq,
              zero_expected_tweet_freq, text)

if __name__ == '__main__':
    main()

データ読み込みと集計

def read_daily_data(filenames):
    num_tweet_distribution = np.zeros(MAX_TWEETS)
    for filename in filenames:
        df = pd.read_csv(filename)
        for tweet_of_day in df[COL_TWEET_COUNT].values:
            # 1日のツイート数の分布を調べる
            num_tweet_distribution[tweet_of_day] += 1
    return np.array(num_tweet_distribution, dtype=np.float64)

ポアソン分布の分析

今回は2種類の理論分布を調べました。

はじめはシンプルなポアソン分布だけを調べたのですが、ツイート数が0の日がとても多いことからデータへの当てはまりがとても悪く、モデルの検討を余儀なくされました。そこで、ツイート数が0かどうかをベルヌーイ分布に従って決定し、ツイート数が0でなければポアソン分布に従う、というtwo-part Poisson 分布を用いました。

ポアソン分布

ポアソン分布の密度関数は以下のように与えられます。日本語で説明すると、「単位時間あたりに平均 λ 回生じる現象が、単位時間に k 回起きる確率」です。

 \displaystyle
f(x) = \frac{(e^{-λ}λ^k)}{k!} (k = 0, 1, \ldots)

ポアソン分布には以下のような特性があり自分の感覚としても、この特性は自分のツイート数の分布に合致しているのでは?と思っていました。 - ポアソン分布は低頻度で発生する現象に対して当てはまりがよく、よく使われます。

  • 低頻度で発生することでも、一気にたくさん発生することもある。ex) 飛行機事故の分布
  • パラメータλは分布の平均値であり、これは分散でもある。

実装ではデータの平均値からパラメータλ(プログラム中の変数mu)を求めています。関数calc_poisson_distributionを参照)

Two-part ポアソン分布

Two-part ポアソン分布とは

普通のポアソン分布で当てはまり具合を調べてみるとツイート数が0の日があまりにも多く(観測値)、理論値と乖離がありました。

実はこのように回数0の頻度がとても多い分布はよくある話で、例えば飛行機事故なんかではそもそも飛行機が飛んでない日があるとするとその日の事故数は0としてカウントされます。

Two-part ポアソン分布のTwo-part とは、

  1. ベルヌーイ分布によって、そもそも飛行機が飛ぶか飛ばないかを決定
  2. ベルヌーイ分布の結果に応じて変動
    1. 飛行機が飛ばないなら事故数は0
    2. 飛行機が飛ぶならポアソン分布に従って事故数がモデル化される

という、二段階で考えることを意味します。 私の場合でいうと、仕事が遅くまであって疲れてて or 旅行にいっていて Twitterをそもそも開けていない日は当然ツイート数が0になるというわけです。

Two-part ポアソン分布の実装

適切な実装方法はわからないので、適当に実装しています。 データからツイート数0の頻度を計算し、それを0の発生頻度とします。 1以上の頻度に対してポアソン分布のパラメータを計算し、合体させたものを理論度数としています。

その他の対処方法案

ゼロ過剰ポアソン分布は実装が面倒だったので妥協しています。

  • 集計期間を広くする

一日のツイート数ではなく、一週間のツイート数など、集計期間を長くとることで分布を調整する方法が考えられます。しかし、この方法ではポアソン分布になるかどうか怪しい & 期間を長くしすぎると中心極限定理が働いて正規分布になってしまって面白くない。

def calc_poisson_distribution(distribution):
    # (e^{-λ}λ^k)/k! に従うかどうか検定
    # λ = 未知母数 (データから推定する)
    # X = クラス k(K回事象が起こる)

    # パラメータλを標本平均から推定する
    mu = calc_mean(range(len(distribution)), distribution)
    # 推定されたパラメータλからポアソン分布に従う場合の期待分布を求める
    poisson_distribution = np.zeros(MAX_TWEETS)
    for x in range(MAX_TWEETS):
        poisson_distribution[x] = calc_poisson(mu, x)
    return poisson_distribution


def calc_zero_inflated_poisson_distribution(distribution):
    zero_num = distribution[0]
    zero_rate = distribution[0]/np.sum(distribution)
    # パラメータλを標本平均から推定する
    mu = calc_mean(range(1, len(distribution[1:])), distribution[1:])
    # 推定されたパラメータλからポアソン分布に従う場合の期待分布を求める
    poisson_distribution = np.zeros(MAX_TWEETS)
    for x in range(1, MAX_TWEETS):
        poisson_distribution[x] = calc_poisson(mu, x)
    poisson_distribution[0] = zero_rate
    after_zero = poisson_distribution[1:] * np.sum(distribution[1:])

    return np.array([zero_num] + list(after_zero), dtype=np.float64)


def calc_mean(xs, distribution):
    sum_ = 0
    for x, freq in zip(xs, distribution):
        sum_ += x*freq
    mu = sum_/np.sum(distribution)
    return mu


def calc_poisson(mu, x):
    e_mu = np.e ** mu
    return mu**x / (e_mu * scipy.misc.factorial(x))

χ二乗検定

あるデータが特定の分布に従っているかどうかを判定するにはχ二乗検定を用います2。χ二乗統計量は以下の式で与えられます。

 \displaystyle
\chi^2 = \sum \frac{(observed - expected)^2}{expected}

数学的な説明を取っ払うと、観測値と期待値の自乗誤差和を期待値で割って正規化しています。確率変数に基づく計算をやると、χ二乗分布に従うことが確認でき、この値がχ二乗分布から大きく外れているとχ二乗分布であることが棄却され、2つの分布は異なる分布であるという結論が導かれます。

今回の場合は同一の分布であることを確認したいので、χ二乗値が自由度((7-1)×(2-1)=6)の上側有意確率0.05のχ二乗値12.6よりも小さいと嬉しいです。

def chi_square_test(data_freq, expect_freq):
    def calc_df(shape_):
        df = 1
        for len_ in shape_:
            df *= (len_ - 1)
        return df
    chi_square = np.sum(((data_freq - expect_freq)**2)/expect_freq)
    df = calc_df(data_freq.shape)
    text = 'X-squared = {:.4f}, df = {:d}'.format(chi_square, df)
    print(text)
    return (text)

可視化

matplotlibで、 - 観測データの分布(Observed) - ポアソン分布の理論分布(Poisson) - Two-parat ポアソン分布の理論分布(two-part Poisson) を可視化しています。

def draw_hist(data_dist, expect_dist, two_part_dist, text):
    fig, ax = plt.subplots(1)
    ax.set_title('Target period: 2020/09/01~2020/12/31')
    ax.bar(np.arange(len(data_dist)), data_dist,
           width=0.2, label='Observed', color='#008000')
    ax.bar(np.arange(len(data_dist))+0.2, expect_dist,
           width=0.2, label='Poisson', color='salmon')
    ax.bar(np.arange(len(data_dist))+0.4, two_part_dist,
           width=0.2, label='two-part Poisson', color='lightblue')
    ax.legend(loc='best')
    ax.text(1.5, 50, text)
    ax.set_xlabel('Tweets per day')
    ax.set_ylabel('freq')

    plt.show()
    plt.close()

結果

f:id:ryuiso2:20210112000955p:plain
ツイート数分布の観測値と理論分布

  • 普通のポアソン分布はデータと当てはまりが悪い
  • Two-part ポアソン分布はデータにかなり適合しており、統計的にも有意差なし(=定性的な結果も踏まえて同じ分布といっても良い。)

考察(というか感想)

  • 無意識にツイートしていただけなのに、(条件はつくものの)ポアソン分布に従うことがわかって驚き
  • よくツイートする人なら一様分布や正規分布のような形になるのだろうか。
  • ポアソン分布に従っているからといって特に何か知見が得られたわけではない。あまりツイートしていないことが再確認された。
  • 普通のポアソン分布の方をRでも一致することを確認済。
o <- c(75, 20, 12,  7,  3,  3,  2)
e <- c(5.20165547e+01, 4.43419811e+01, 1.88998608e+01, 5.37045225e+00,
       1.14452261e+00, 1.95131724e-01, 2.77236329e-02)
chisq.test(o, p = e / sum(e))
qchisq(.95, df=6)  # χ二乗値の確認 12.59159
# 出力結果:
    Chi-squared test for given probabilities

data:  o
X-squared = 210.16, df = 6, p-value < 2.2e-16

  1. 実装や理論で気になること、指摘などありましたらコメントしてくださいますと幸いです。

  2. ある分布とある分布の近さを計算するにはかカルバック・ライブラー距離を用いますね。

高知旅行

f:id:ryuiso2:20200224222850j:plain
高知県

観光地

沈下橋

沈下橋とは欄干*1がなく、簡易的に作られる橋です。なお、沈下橋という名前ですが、増水時以外は普通に橋として機能しています。

高知県には「日本三大清流」の一つである四万十川が流れておりそこから派生する仁淀川など、水質が良い川が多い。それらに架かる沈下橋は絶景です。

名越屋橋(沈下橋

f:id:ryuiso2:20200224231408j:plain
名護屋

f:id:ryuiso2:20200224231448j:plain
名護屋橋からの景色

  • アクセス:高知市の中心地から車で約30分
  • 所要時間:橋を見て写真を撮るだけなら10分程度
  • 余談:四万十川よりも水が綺麗と言われている仁淀川に架かる沈下橋の中で最長の長さ

高知城

天守が現存するお城12城うちの一つです。

f:id:ryuiso2:20200224231420j:plain
高知城
f:id:ryuiso2:20200224231436j:plain
高知城天守

  • アクセス:高知市の中心地から徒歩15分
  • 所要時間:急ぎ目で回って40分
  • 余談:高知城を治めていたのは山内一豊という人*2で、長宗我部信親がいたわけではない。

ひろめ市場

f:id:ryuiso2:20200225003329j:plain
ひろめ市場の中:市場というよりも飲食街、土産屋といったイメージ。

  • 市場という名前がついていますが、飲み屋街みたいなイメージです。
  • お土産を買うのにもいい場所です。
  • 目の前で藁で鰹を炙ってくれるお店もあります。

食べ物

鰹料理

f:id:ryuiso2:20200224235339j:plain
鰹料理

  • 鰹のタタキはタレではなく塩、レモン、にんにくでいただく
  • お造りはオレンジを絞ることも
  • 土佐巻:鉄火巻の鰹バージョン。個人的に一押し。

クエ鍋

f:id:ryuiso2:20200224235646j:plain
クエ鍋:花が開くときが食べごろ

  • 高級魚として有名
  • 白身魚にして油がしっかり乗っている
  • コラーゲン感が強く、ポン酢なしでそのまま食べるとくどいかもしれない
  • ポン酢をつけ過ぎるとポン酢の味しかしない(当たり前)

鰹料理とクエ鍋は 土佐料理 司 でいただきました。

炙り鯖寿司

f:id:ryuiso2:20200225000940j:plain
炙り鯖寿司

  • 見た目や名前で想像するよりも美味しかったです。
  • ひろめ市場で購入し、翌日の朝食でいただきました。

ゆずサワー

f:id:ryuiso2:20200226220520j:plain
ゆず。他にも「直七」などの柑橘類が有名です。

  • ひろめ市場にて購入(100円)
  • 居酒屋にいくと直七サワーなるものがあったりします。
  • 近くの商店街やひろめ市場で買える唐揚げと相性抜群
  • 高知県は鶏肉も有名なようです。

*1:橋から落ちないようにする柵みたいなやつ

*2:関ヶ原の戦い前後で活躍して徳川家康土佐国一国・9万8,000石を与えられ、移り住んだ。

京都マラソン2020を終えて

はじめに

f:id:ryuiso2:20200218210846p:plain

筆者が参加した京都マラソン2020回顧録です。

筆者の運動経験は中学生のときに3年間「市内~都道府県大会レベル」の運動部に所属していた以来、まともな運動をしていません。 また、筆者はメーカー勤務の技術者であり、主な練習は休日のみでした。

そんな筆者が42.195kmを5時間30分で完走するまでにやったことなどをまとめておきます。

練習について

概要

  • 練習期間:2019年9月1日~2020年1月16日(5ヶ月半)
  • 練習回数:平日1日、土日のどちらか1日(週2日)*1

練習内容

  • 始めの2ヶ月は平日3km, 休日5km
  • 次の2ヶ月は平日5km, 休日10km
  • 最後の1ヶ月は平日10km, 休日15km
  • 本番の道を前半、後半に分けて20kmずつ走る練習を12月と1月に実施

いずれもペースは体調に合わせて6~7分/km 程度

購入したもの

  • JYURYUトップス
    • 上に着るインナーウェア。
    • 背筋が曲がらないように支えてくれ、ランニングのフォームを維持してくれます。
    • 保温性
    • 吸汗速乾
    • 雨の中でも上半身を冷やすことなく完走できました。
  • スポーツタイツ
    • 膝、太ももの負担軽減
    • 下半身の保温
  • ソックス
    • ワコール製の5本指セパレート型
    • 足指がこすれることによるトラブルが減るので指が分かれているのがおすすめです。
    • 足首を保護してくれるのも心強い
  • ウエストポーチ
    • 腰、肩、いろいろつけるところがありますが、につけるのが一番揺れにくくオススメらしいです*2
    • ラソン当日はスマホエナジージェル×3、タオル、ティッシュペーパーを入れていました。
    • 慣れるために練習の時からつけるようにしていました。
  • エナジージェル
    • 170kcalのジェル×3
    • 10km, 20km, 30km地点付近で1本ずつ小分けにして飲みました。
    • サイズが小さく、高カロリーなものを選びました。

ワコール製品は高価ですが、知人、スポーツ選手からの評判がとてもよく、実際の使用感もとてもよかったです。 筆者は他製品と比較したわけではありませんが、おすすめの商品です。

走法

個人的な試行錯誤、マラソンが趣味の知人から聞いたことの中から実践してよかったと思うものを列挙します。

  • 足を高く上げすぎない

    • 基本的に身体を動かす量が少ないほうがいいという考えに基づいています。
  • かかとから地面に着地する

    • 足のへの衝撃を上手に分散させるためにも、かかとからつま先の方へなめらかに地面に足をつけるように走ります。
    • 意識しすぎると足を前に出しすぎて変な力が入ります。私は自然にかかとから着地できるようになるには練習が必要でした。
  • ストライドを小さくする

    • ストライドとは、一歩の距離[m]を指す。
    • 身長の0.6~0.7倍が理想らしいです。
    • 男性の方が筋力があり、大きい値になりがちだが、大きくなると足への負担が大きくなり、マラソン後半が辛くなりやすいです。
    • 初心者で完走を目指したい人はこの値を小さくします。
    • 早く走りたい人はこの値を大きくします。
    • プロのマラソン選手はこの値が1.0を超えるらしい。
    • この値が測れるスマホアプリを入れて練習してください。
  • ピッチを高くする

    • ピッチとは、1分間に何歩足を出すかを表す数値*3
    • 180/分 が理想らしいです。
    • 女性はこの値が大きくなりやすく、最後まで走り続けられる人はこの値が大きいらしいです。
  • 腕ぶらぶら走行

    • 長時間走っていると、肘の表(?)が痛くなります。
    • たまに腕をぶらぶらさせたり、ストレッチを行うことが重要です。
    • 筆者は下り坂や2kmおきになど、高頻度に腕を伸ばすように意識していました。
  • 上半身を起こす

    • 猫背や前傾姿勢は長時間走り続けるのに適しません。
    • 日常生活から姿勢よく過ごすよう意識していました。

コース攻略

f:id:ryuiso2:20200218232205p:plain
京都マラソン2020コース

0~5km地点(西京極~嵐山)

  • スタート時は前がつっかえて走れません。
  • 以下の理由で周りのペースが上がるので、自分のペースでゆっくりめに走りましょう。
    • 走れるようになる頃(15分後くらい)になると、ようやく走れるという開放感
    • 本番で気持ちが高ぶる
    • 周りのペースが上がっていることによりさらにつられて周りが早くなる。

5~15km地点(嵐山~大覚寺

  • アップダウンが激しい
  • 周りに抜かされても、ペースを落として体力の温存を優先したいです。

15~27km地点(大覚寺~加茂川河川敷)

  • 平坦で単調な道が続く
  • 身体的には走りやすいが、直線が多いので気持ち的に長く感じます。
  • 栄養補給、沿道の応援を楽しみながら、少しペースを上げて走ります。
  • 次のエリアではペースを上げにくいので、ここで少し前に出ておくのが良いかもしれません。

27~32km地点(加茂川河川敷~河原町丸太町)

  • 河川敷は狭く、足場も悪いので走りにくかったです。
  • 雨天時には足を取られるので体力も消耗します。
  • 道幅が狭い、ペースが落ちているランナーが増えてくるので、前の人を抜かすのが難しくなりペースを上げにくかったです。

32km~39km 地点(河原町丸太町~京大今出川通

  • 「30kmの壁」と呼ばれる最も辛いエリア。
  • 身体への負担がピークを迎えて関門*4を突破できなくなる人が多いゾーン。
  • かなりつらいですが、ここまで来たのだから最後まで頑張りましょう。
  • ここ以前にエナジー系のジェルを飲み切りましょう。*5

39km~ゴール(京大今出川通平安神宮

  • 緩やかな坂道が今出川通りで続きます(上り→下りの折返し)。
  • 疲労が溜まっている中での上り坂で歩く人も多いです。
  • 今出川通りの下り坂の後、もしくはもうしばらく進んだ後くらいからラストスパートをかけます。

ラソン当日周辺

一週間前の過ごし方

  • 身体にエネルギーを供給する肝臓に負担をかけないように心がけましょう
    • 禁酒
    • 過剰にタンパク質を摂らない(肝臓に負担がかかる)
    • 炭水化物を中心に摂取
    • お腹の調子を整えるためにヨーグルト

前日の過ごし方

  • 平安神宮にて受付を行う
  • 受付でもらったゼッケンをウェアにつけておく
  • 荷物をまとめる

服装

  • 5本指靴下
  • 下半身タイツ
  • ハーフパンツ
  • 上半身タイツ
  • 速乾性のスポーツウェア
  • 手袋(末端を冷やさないことが重要)
  • 帽子(雨をしのいだり髪の毛が邪魔にならない)
  • レインコート(防寒、防雨。途中で脱ぎ捨て可能)

朝食

  • 普段から食べ慣れているものを食す。
  • 筆者はお餅3個入りのお雑煮+ソーセージ4本。

ラソン後の過ごし方

  • ラソン後の夕食はタンパク質を補給するのがいいと思っていたが、あまり食欲がわかなかったので、食べやすいものが良いです。
  • 次の日からは食欲が回復したので、そこでタンパク質を補給しました(肉)。

注意事項

インスリンショック

  • エナジージェルを補給すると血糖値が急激に上がり、その後低血糖になることでパフォーマンスが下がる現象に注意
  • 対策はエナジージェルを補給する際は水分を同時に摂る、ジェルを小分けに摂取しましょう。

低体温症

  • 身体をガクガクさせて体温の維持を図るが体温が上がらない状態。
  • 冬場のマラソンではプロ選手でも陥る可能性があります。
  • 対策は末端を冷やさないように手袋やウェアに注意を払う。
  • (個人的に)歩いたり立ち止まると汗で冷えてしまう気がするので、遅いペースでも走り続けましょう。

最後に

練習内容を振り返ると十分な練習量とは言えないでしょう。それでも完走できたのは、沿道の力強い応援、給水給食荷物管理などのボランティアの方々、レースを共にしたランナー、応援してくれた家族や友人の支えがあってこそだと思います。独りでは到底走りきれる距離ではありませんでした。ありきたりな文面で恐縮だが、この気持を忘れないように改めて感謝の気持をここに残します。ありがとうございました。

SNSで走る宣言を大々的にして、友人に応援してもらうことで、レース中に心が折れそうになったときにも、「ここで終わるわけにはいかない」という気持ちになれました。

平安神宮のゴール後に完走記念タオルをいただきました。雨の中のあのタオルの暖かさと肌触りに安心感のようなものを覚えました。いろんな人の応援や達成感も相まって、まさに万感の思いでした。マラソンはリピーターが多いといわれています。リピーター達は、フルマラソンのゴールでしか味わえないあの感覚と、レースを共有する仲間を求めているのかもしれません。

*1:残業が多い時期や旅行に行ってる時は練習ができないので、週2日の練習ができた週の方が少なかったかもしれません。

*2:スポーツショップの店員さんが言ってました

*3:ストライドとピッチが決まると走行速度が決まります。理想的に走るとフルマラソンを3.5時間程度で完走できる計算になります。

*4:関所が8箇所くらいあって、制限時間以内にそこを通過しないと完走できなくなります。基本的に6時間完走を下回るペースだとアウト。

*5:吸収の早いものでも口にしてからエネルギーとして使えるようになるまでに30分以上かかるので、35km地点以降で摂取してもレースに無関係となってしまいます。

ストーリープレイで学ぶgit

基本事項

  • ワークツリー
    • 実際に作業を行っているディレクトリであり、編集を行った最新のファイルが存在する。
    • ここでの作業内容をgit addすることでインデックスに変更を登録する。
  • インデックス
    • ローカルリポジトリにコミットを行う準備をする場所。ワークツリーから登録された内容をgit commitでコミットする。
    • インデックスが存在することで、ワークツリー内の必要のないファイルはコミットしないといったことができる。
  • ローカルリポジトリ
    • ローカル環境内でのプロジェクトのファイルやディレクトリの変更履歴を記録する場所。
  • リモートリポジトリ
    • サーバに配置されており、複数人でプロジェクトを共有する場所。
  • チームで開発するときは大前提として master ブランチで作業はしない
## 作業を始める前に行うコマンド
$ git status  # 変更がなかったか確認する癖をつける
$ git branch  # 今どのブランチで作業しているかに注意 c.f. vscoeの場合

## 作業が一段落したときに行うコマンド
$ git add -A  # 変更ファイルのadd
# ローカルリポジトリにコミット。コメントを書くことができる
# コメントの書き方については後述。
$ git commit -m "coments"  
# push すると、ローカルリポジトリの内容をリモートリポジトリにアップロードできる
$ git push remote リモートリポジトリ名 # リモートリポジトリにあげる。多くの場合 リモートリポジトリ名 = origin

## 変更を取り込みを行い場合
# fetch を行うと、リモートの情報をダウンロードできる
$ git fetch リモートリポジトリ名  # 多くの場合 リモートリポジトリ名 = origin
$ git merge ブランチ名  # 今いるブランチにブランチ名の内容をマージする

ロールプレイング

branch を発行して 作業

  • 先輩A「NNモデルにショートカットコネクションを追加してほしい     あ、新しくブランチを切って開発してね」
  • 後輩B「わかりました!!」
## 開発前の準備
$ git fetch  # 後輩Bのローカルリポジトリを最新の状態にする
$ git branch -a  # ブランチ一覧を表示し、どのブランチから新たなブランチを切るか考える
$ git checkout -b 新たなブランチ名 切る元のブランチ  # ブランチの作成+ブランチの切り替え
$ git checkout -b shortcut develop  # ブランチの作成+ブランチの切り替え
$ git branch  # 新たなブランチが無事できたか確認(正しくブランチ切り替えができているか)

### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
### 適宜 commmit や push をしながら実装ショートカットコネクションを実装
###  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

## 開発完了後のマージ
$ git status  # 自分が更新したファイルを確認
$ git add -A  # 変更の更新
$ git commit -m "コミットメッセージ"  # commit
$ git push push origin ブランチ名  # 現在の作業ブランチ名を入れる 初回は新しくリモートにそのブランチが作成される
$ git push origin shortcut  # 現在の作業ブランチ名を入れる 初回は新しくリモートにそのブランチが作成される

merge (他人の作業 branch の取り込み)

  • 後輩B「ショートカット追加しましたので、新たなブランチ名 で push しときました!」
  • 先輩A「ありがとう!!」
  • 先輩A「後輩Cさん、後輩Bさんがショートカット作ってくれたので、取り込んで実験の続きしといてください。」
  • 後輩C「承知しました。」
$ git fetch
$ git branch -a # どのブランチを取り込むか確認(「Bさん、このブランチであってますか?」)
$ git branch  # 現在いるブランチの確認
$ git checkout develop  # 自分の作業ブランチに移動
$ git merge 更新元のブランチ名  # 今Cさんは更新先(させたい)ブランチ(develop)にいる
$ git merge shortcut  # 今Cさんは更新先(させたい)ブランチにいる

### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
###  Cさんは現在いるブランチにBさんの更新内容を取り込んだので、開発を再開・完了
###  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

$ git commit -m "[update] ショートカットつきで実験完了"
$ git push origin push master  # 動作するバージョンができたので master に push

## 注意
$ git pull  # は非推奨
git pull == git fetch + git merge

不要 branch の削除

  • 後輩C「Bさん、作業完了したので shortcut ブランチは消していいですよ」
  • 後輩B「あとでやっておきます。」
  • 取り込みが終わった branch は不要なので(もし修正が必要なら修正用の branch を再度発行する)どんどん消していく
## ローカルブランチの削除
$ git branch
$ git branch --delete shortcut  # ブランチの削除

## リモートブランチの削除
$ git branch --remote
$ git push --delete origin shortcut  # git push origin :shortcut でも可

conflict (マージ時の競合) 対応

  • 先輩A「Bさん、そろそろ手が空いてきた?Cさんの実験手伝ってあげて」
  • 後輩B「わかりました。では、Cさんの最新のdevelopブランチを取り込んでハイパラいじってみよう」
$ git fetch
$ git merge develop
CONFLICT (content): Merge conflict in hoge.py
Automatic merge failed; fix conflicts and then commit the result.   
  • 後輩B「あれ?なんかうまくいかない?    Cさん、どっちのバージョンを残しましょうか?」
  • 後輩C「あー、こっち間違えてcommitしてたごめん。こっちを消してあっちを残しておいて。」
### ~~~~~~~~~~~~~~
###  Bさんは不要な行を削除する。
###  ~~~~~~~~~~~~~~
$ git add -a
$ git commit 

stash (退避)

  • 後輩C「無事競合を解決できたから実験がんばるぞー!」
  • 先輩A「あ、Cさん、急いで畳み込み部分のバグを修正してもらえないかな?」
  • 後輩C「わかりました!(今作業途中なんだけどこのブランチどうすればいいんだろう)」
$ git checkout ブランチ名
error: Your local changes to the following files
 would be overwritten by checkout: sample01.py
Please commit your changes or stash them before you switch branches.
Aborting
$ git stash save -u "スタッシュ名"  #スタッシュ名は後で一時退避から復活させる時に、どれを復活させるか見分けるためにわかりやすいものにしましょう。
$ git checkout ブランチ名

### ~~~~~~~~~~~~~~
###  Cさんはバグ対応を完了させる。
###  ~~~~~~~~~~~~~~

$ git stash list  # スタッシュしたリストを確認
$ git stash pop スタッシュ名  # 復活&スタッシュリストからの削除
  • 後輩C「これで前の実験に戻れる。あ、さっき自分が直したバグ修正を mergeしないと!」

fork して共同開発

commit コメントの書き方

  • qiitaの記事 にいいねが多かった (3847いいね)のでこれがいいのかも?

*1行目:変更内容の要約(タイトル、概要)2行目 :空行3行目以降:変更した理由(内容、詳細)

1行目 (コミット種別と要約)

  • コミット種別は以下の通り
    • fix:バグ修正
    • add:新規(ファイル)機能追加
    • update:機能修正(バグではない)
    • remove:削除(ファイル)
  • 要約はシンプルにわかりやすく
  • 例:
    • [update] 渋滞日報を元に学習データを作成するように変更
    • [fix] 渋滞発生回数の記録が両方trainになっていたのをtrain, testに修正

2行目(空行)

3行目 (変更した理由)(文字制限もあるので書かなくていいかもしれない)

  • 私は書いてません。

commit の粒度頻度 (私の意見)

  • commit コメントの要約文が完結である間に commit する。
  • ソースコードのどの辺りを編集したか特定できる間に commit する。
  • 要するに細かく commit しましょう。

pytorch でハマりやすいポイント

f:id:ryuiso2:20200113014149p:plain
title

pytorch (pytorch=1.1.0)

基本的にはレファレンスを参照するが、躓きやすいところを中心にメモを残す。

GPUの使用

  • ソースコード中に明示的にGPU用変数に設定する必要がある。

  • モデル、変数、計算に関わるものすべてを .to(device) しなければならない。

  device = 'cuda'
  CNN().to(device)
  
  # 以下のように書くと便利
  import torch
  device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
  • 正しくGPUが使用できているかの確認は
  nvidia-smi -l

GPUの使用率を確認する。

Parameter の作成

  • Parameter とは、学習によって調整する学習パラメータのことである。

  • 括弧 () の順番が大切で[dim1, dim2] のサイズのパラメータを作成する際は、以下のように書く。

  import torch.nn as nn
  nn.Parameter(torch.Tensor(dim1, dim2).to(device))

tensor shape の確認

  • tensorの型を確認、取り出すには .size()を用いる
print(torch_tensor.size()) # タプル型を表示

cross-entropy loss (classification)

  • cross-entropy loss を用いる際、教師信号で与えるラベルは微分可能でかつ、long型でなければならない
from torch.autograd import Variable
y = Variavble(y).long().to(device) # Variavble()で微分可能に、long()でキャスト

DataLoader

  • DataLoader とは、pytorch で学習する際にデータをミニバッチサイズに応じて取り出すイテレーターである。

  • 一度TensorDataset を作成する必要がある。

from torch.utils.data import TensorDataset, DataLoader
  ## 学習前の準備
  ds = TensorDataset(x, y)  # TensorDataset の作成
  loader = DataLoader(ds, batch_size=BATCH_SIZE, shuffle=True)  # DataLoaderの作成
  
  ## 学習時
  for itr, (x, y) in enumerate(loader):
      # x, yを使って学習させる。

モデルの評価 (GPUメモリの節約)

  • pytorchでは計算履歴を変数が保存するので、すぐにGPUメモリを枯渇させてしまう。

  • 計算履歴を保存する必要のない評価時には、保存しない設定で計算すべき。

  • with torch.no_grad(): の中で実行すればよい。

  with torch.no_grad():
      model_forward() # ここに必要な処理を書く。

torch 変数の取り出し

  • そのままでも値を取り出すことはできるが、計算履歴を含まない値を取り出すにはitem() を使う
torch_tensor_value = torch_tensor.item()
  • また、GPU変数をnumpyに取り出す際には、.cpu().detach().numpy()として取り出す。
numpy_array = gpu_tensor.cpu().detach().numpy()