Open victor-von-pooh opened 7 months ago
@tottocoslowlifer
まずは, 現段階で全ての README.md
ファイルに記載漏れが無いかを確認し, requirements.txt
を更新した上で,
データ分析で行ったものと同じようにして preprocessed_df を作成し, 新たに csv ファイルを作成するスクリプトを tide/scripts に用意する
こちらを終わらせましょう.
README.md
ファイルに追記する内容は特にありませんでした.
requirements.txt
に関してですが,今回,新たに追加したものは
from scipy import signal
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from statsmodels.tsa.seasonal import STL
from statsmodels.tsa.stattools import adfuller
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
です.
scipy
, sklearn
, statsmodels
のうち,書く必要があるものはどれでしょうか.
numpy
やpandas
のように直接,importと書いていないため,どうなのかが気になりました.
すみません, 完全に見落としていましたが,
from scipy import signal
こちらがどこにも使われていないようなのでまず notebook から削除してください.
scipy, sklearn, statsmodelsのうち,書く必要があるものはどれでしょうか. numpyやpandasのように直接,importと書いていないため,どうなのかが気になりました.
外部ライブラリなので全てです.
import xx
は文字通りライブラリ xx
そのものをインポートするものですが, from xx import yy
は xx
にある yy
をインポートするという意味であり, そもそも xx
が環境下にない場合はエラーが起きてしまいます.
今回,
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from statsmodels.tsa.seasonal import STL
from statsmodels.tsa.stattools import adfuller
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
となっているので, Scikit-Learn と Statsmodels が必要になります.
それぞれ,
pip3 install scikit-learn
pip3 install statsmodels
でインストールできると書かれているので, requirements.txt
への追記は
scikit-learn
statsmodels
になります.
かしこまりました.ありがとうございます.
notebookおよびrequirements.txt
をコミットいたしました.
確認が取れました. 引き続き,
データ分析で行ったものと同じようにして preprocessed_df を作成し, 新たに csv ファイルを作成するスクリプトを tide/scripts に用意する
こちらの対応をよろしくお願い致します.
ご確認ありがとうございます.
preprocessed_csv_convert.py
を新たに作成いたしました.
よろしくお願いいたします.
確認が遅くなってしまい, 大変申し訳ございませんでした. また, 実施事項に不備があり, 伝え損ねたことがありましたので, ご対応のほどよろしくお願い致します.
データ分析で行ったものと同じようにして preprocessed_df を作成し, 新たに csv ファイルを作成するスクリプトを tide/scripts に用意する
$$\downarrow \quad \downarrow \quad \downarrow$$
データ分析で行ったものと同じようにして preprocessed_df を作成し, メタ情報を使った重回帰分析による予測で欠損値を補完した後の DataFrame を新たに csv ファイルとして保存するスクリプトを tide/scripts に用意する
かしこまりました. 修正が完了したので,ご確認の程よろしくお願いいたします.
@tottocoslowlifer ご対応いただきありがとうございます. 以下コメントになります.
preprocessed_csv_convert.py
について, 以下の変更を加えてください.
call_moji_tide()
関数, call_mooncal()
関数, call_shimonoseki()
関数の if 文と else 文の間の1行のインデントエラーを無くす[x] call_shimonoseki()
関数139行目の
df.loc[i, item] =- float("nan")
を
df.loc[i, item] -= float("nan")
に直す
[x] train_predict()
関数を次のように修正する
def train_predict(X, y, split_rate):
X_train, _, y_train, _ = train_test_split(
X, y, test_size=split_rate, random_state=316
)
regressor = LinearRegression().fit(X_train, y_train)
return regressor
ありがとうございます. 再度コミットいたしました.
@tottocoslowlifer ありがとうございました. LGTM です.
続いて,
セットアップツールを作成する
こちらに移りたいと思うのですが, この目的があまりわからないと思うので軽くご説明します.
各モデルを使った結果の精度を上げるために, 実験を繰り返してパラメータを調整しなければいけない. $\rightarrow$ 各実験の詳細情報を記録する必要がある.
tide/experiment_tools
フォルダ実験において必要になるセットアップ関連のツールを管理するフォルダ.
それぞれのモデルの実験において, これらを使うことを徹底する.
いきなりセットアップツールの作成は難しい. $\rightarrow$ まずは必要なものを検討したい.
また, 乱数などは指定を出来るようにしたい. このような場合, モデルごとに config(configuration) というものを作る. config ファイルを参照し, モデルのパラメータの調節を行う. こちらの感覚にまずは慣れておきたい.
tide/config
フォルダを作成し, その下に default
と experiment
の2つのディレクトリを作るtide/outputs
フォルダを作成するtide/config/default/test.json
ファイルを作成する(これは後で削除する)
{
"log": {
"log_file": "../outputs/test.log",
"log_formatter": "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
},
"name": "tottocoslowlifer",
"greeting": "こんにちは!",
"reps": 10
}
[x] 続いて, tide/scripts/logs.py
ファイルを作成する(これも後で削除する)
import json
import logging
from logging import getLogger, FileHandler, Formatter
import subprocess
def set_logging(cfg):
logger = getLogger(__name__)
logger.setLevel(logging.INFO)
handler = FileHandler(cfg["log"]["log_file"], mode='w')
formatter = Formatter(cfg["log"]["log_formatter"])
handler.setFormatter(formatter)
logger.addHandler(handler)
return logger
filename = "../config/default/test.json"
with open(filename) as f:
cfg = json.load(f)
logger = set_logging(cfg)
git_info = "commit id: "
git_info += subprocess.check_output(
['git', 'rev-parse', 'HEAD']
).decode().strip()
logger.info(git_info)
logger.info(f"username: {cfg['name']}")
logger.info(cfg["greeting"] * cfg["reps"])
tide/outputs/test.log
ファイルを確認するここで行われているプログラムの流れを全て理解するところから始める.
実験を繰り返し行う上で,
を明示するために,configファイルを作成する.
各モデルの実験ごとに別ファイルを作成するが,まずは標準的なものとしてtide/config/default/test.json
ファイルを用意している.
tide/scripts/logs.py
ファイルについてimport json
import logging
from logging import getLogger, FileHandler, Formatter
import subprocess
def set_logging(cfg):
logger = getLogger(__name__) # loggerオブジェクト "__name__" の宣言
logger.setLevel(logging.INFO) # ログレベルをINFOに設定
handler = FileHandler(cfg["log"]["log_file"], mode='w') # ここでは "../outputs/test.log" を書き込みモードで開く
formatter = Formatter(cfg["log"]["log_formatter"])
handler.setFormatter(formatter) # handlerのformatは "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
logger.addHandler(handler) # loggerにhandlerをセット
return logger
filename = "../config/default/test.json"
with open(filename) as f:
cfg = json.load(f) # グローバルなオブジェクトとしてのcfgを宣言
logger = set_logging(cfg) # グローバルなオブジェクトとしてのloggerを,cfgを元に宣言
git_info = "commit id: "
# $ git rev-parse HEAD の出力結果をgit_infoに追加(最新のコミットハッシュ(修正内容と修正者の情報)が記録される)
git_info += subprocess.check_output(
['git', 'rev-parse', 'HEAD']
).decode().strip()
# 以下,ログレベルのINFOを超えているため出力される
logger.info(git_info) # 実験を行った時点のレポジトリの状態
logger.info(f"username: {cfg['name']}") # 実験を行った時点のGitHubのコミットID
logger.info(cfg["greeting"] * cfg["reps"]) # cfg内のgreetingをrepの数だけ繰り返し
長くなってしまいましたが,目を通していただけたら幸いです.
また, greeting
の意義をよくわかっていないのですが,実際にどういった用途に用いるものか,教えていただけたら幸いです.
@tottocoslowlifer ご対応ありがとうございます. 以下コメントになります.
tide/scripts/logs.py
ファイルのコメントアウトについて, 「#」の後にスペースを1つ空けているのは良いです◎
Python のコメントアウトの正しい記法になります.
では, そのコメントアウトについてですが,
handler = FileHandler(cfg["log"]["log_file"], mode='w') # ここでは "../outputs/test.log" を書き込みモードで開く
こちらについて, mode='w'
(正しくは mode="w"
です, ごめんなさい)にしている理由としては, tide/outputs/test.log
ファイル上で, 過去の log を上書きするためにしています(ここを指定しないと以前に書かれたものの続きで書かれる).
この .log
ファイルは今後実験ごとに個別で作成する予定なのでどちらでも本当は構いません.
また, greetingの意義をよくわかっていないのですが,実際にどういった用途に用いるものか,教えていただけたら幸いです.
ご質問ありがとうございます. 意義は, ありません.
今回のワークのポイントは次の2つです.
2点目について, tide/config/default/test.json
という json の config ファイルを読み込み, そこから値を抽出するということをしていました.
ここで気にするべきことは, json 形式の config ファイルを扱う際に, そこに書かれた key と value の対応と使える型の確認をすることです.
json のファイルは Python の辞書型と同様に扱えるので, 読み込んでしまえばあとは簡単ではあります.
しかし, value で使える型は str 型のみなのか, int 型や float 型としてそのまま読み込めるのか, 他に扱えるオブジェクトはあるのかなどを考える必要はありますね.
今回,
logger.info(cfg["greeting"] * cfg["reps"]) # cfg内のgreetingをrepの数だけ繰り返し
こちらの1行で str 型である cfg["greeting"]
に cfg["reps"]
をかけるということが出来ています.
すなわち, cfg["reps"]
は int 型でそのまま扱えることがわかります.
実際にプラクティスに入る際には, 例えば Scikit-Learn の決定木回帰モデルを扱うことを考えると, 引数には
これだけのパラメータがあります. 型がバラバラであり, config でしっかりと管理しなければいけません. これを意識してもらうことが狙いでした.
早速のご返信ありがとうございます.
tide/outputs/test.log
ファイル上で, 過去の log を上書きするためにしています
今調べたところ,デフォルトの"a"(コードを実行する度に追記される)に対して,"w"があるのですね.
また,質問に対してのご返答もありがとうございます.疑問が解消されました.
@tottocoslowlifer
今調べたところ,デフォルトの"a"(コードを実行する度に追記される)に対して,"w"があるのですね.
デフォルト値がどうなっているのかご自身で確認する姿勢, 大変素晴らしいです◎ それでは以下の2点についてのチュートリアルが済んだという理解でよろしいでしょうか?
こちらがよろしければ, 早速
セットアップツールを作成する
こちらに移ってみましょう.
まずは tide/scripts/logs.py
, tide/config/default/test.json
, tide/outputs/test.log
の3つのファイルを削除しましょう.
そして, tide/experiment_tools
というフォルダを作成しましょう.
このフォルダ下に
__init__.py
set_up.py
start_logging.py
set_random_seed.py
の4つの空のファイルを用意してください. ここまで出来たらまたご一報ください.
ありがとうございます. コミットが完了いたしました.
@tottocoslowlifer 迅速なご対応ありがとうございます.
それではまず, tide/experiment_tools/start_logging.py
の中身を記述してみましょう.
ここでは, get_logger()
関数を定義しましょう.
引数は cfg
とし, logger
という変数を返り値に持つように log に残すべきだと思われるものの準備をしましょう.
なお, ここでは get_logger()
関数と必要なライブラリの import 以外で記述するものはありません.
コミットいたしました. このようなもので意図と合っていますでしょうか.
はい, プログラムとしては完璧です. 一応型の宣言をしておきましょう.
def get_logger(cfg: dict) -> logging.Logger:
とだけ書き換えておきましょうか. これだけ変更を加えて以下の対応をよろしくお願い致します.
tide/experiment_tools/set_random_seed.py
に fix_seed()
関数を作りましょう.
こちらも tide/experiment_tools/start_logging.py
同様関数を作るだけにします.
参考記事を見て, 必要そうなものを書いてみましょう.
コミットいたしました. 記事によると,TensorFlowに関しては,GPU周りの情報が少ないとのことなので省きました.
@tottocoslowlifer お疲れ様です. 以下コメントになります.
記事によると,TensorFlowに関しては,GPU周りの情報が少ないとのことなので省きました.
OK です. おそらく TensorFlow はこれからも使わないと思うので大丈夫です.
現在, PyTorch を使っていない状況(今後は使う予定あり)ですので, tide/requirements.txt
に torch
と入れておいてください.
このファイル自体の実行はしない為, 最後の2行はいらないです. config ファイルに seed 値を設定するため, ここでは使いません.
ありがとうございます. 再度コミットいたしました.
@tottocoslowlifer ありがとうございます. 追加で, こちらも引数は型の指定をしましょう.
def fix_seed(seed: int):
対応が完了いたしました. よろしくお願いいたします.
@tottocoslowlifer
ありがとうございました.
それでは続いて, tide/experiment_tools/set_up.py
を書いていきましょう.
ここでは, log を残す最初のステップになります.
どのモデルを使用しても, 基本的に中身は変わらない部分になると思います.
まずは, 実験を行う上でどのようなことを log に残すべきかを箇条書きで書いてみましょう.
お疲れ様です. 実験を行った時点の ・日時 ・レポジトリの状態 ・GitHubのコミットID では不十分でしょうか.よろしくお願いいたします.
@tottocoslowlifer お疲れ様です.
実験を行った時点の ・日時 ・レポジトリの状態 ・GitHubのコミットID では不十分でしょうか.
良いところまで考えられていると思います.
これは config の log.log_formatter
にて %(asctime)s
を指定しているため, 各 log においてそれが実行された時間が自動で出力されるので, わざわざ手動で加える必要はありません.
これは, 「変更などを加えることで出力の結果が変わってくるため, どのような条件で実験を行ったかがわかるようにしたい」という意図だと解釈しています. 一方で, GitHub のコミット ID を URL に加えることで, その時のリポジトリの情報は得られるため実質不要です.
https://github.com/tottocoslowlifer/tide/tree/9d642e7aaf3155fc42014e21352b1c9256de6dc1
こちらは必要です.
tottocoslowlifer
など)ありがとうございます.
実験を行った時点の ・日時 ・レポジトリの状態 ・GitHubのコミットID ・実験者のGitHub のアカウント名 ・実行環境 ということでよろしいでしょうか.
@tottocoslowlifer いえ, 次の3つです.
日時については, tide/experiment_tools/start_logging.py
で作った get_logger()
関数9行目,
formatter = Formatter(cfg["log"]["log_formatter"])
ここで config の log.log_formatter
を参照していることがわかります.
config の該当部分には "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
と入れています.
この %(asctime)s
には, 残す log ごとに実行した時の日時が自動で記録されるようになります.
2024-04-06 18:39:48,490 - experiment_tools.start_logging - INFO - commit id: 136d189e646e86d1fdba39d3bf3d615148fb6579
リポジトリの状態については, GitHub のコミット IDを, https://github.com/tottocoslowlifer/tide/tree/hogehoge
の hogehoge
の部分に入れ, リンク先を確認するとその時点でのリポジトリの状態が確認できます.
すなわち, "GitHub のコミット ID" = "その時点のリポジトリの状態の key" ということです.
理解いたしました. ありがとうございます.
それではまず, GitHub の必要な情報を log に残す logger
を引数および返り値にもつ get_git_info()
関数のドラフトをコメント内に書いてみましょう.
def get_git_info(logger) -> logging.Logger:
logger = get_logger(cfg)
git_info = "commit id: "
git_info += subprocess.check_output(
['git', 'rev-parse', 'HEAD']
).decode().strip()
logger.info(git_info)
logger.info(f"username: {cfg['name']}")
return logger
でいかがでしょうか.
cfgは関数外で
filename = "..."
with open(filename) as f:
cfg = json.load(f)
logger = get_logger(cfg)
のように宣言するイメージでいます.
@tottocoslowlifer ありがとうございます. 補足もわかりやすいです.
1点, logger.info(f"username: {cfg['name']}")
については, config で指定するのは大変なので自動で取得できるようにしましょう.
ヒントはその上の
subprocess.check_output(['git', 'rev-parse', 'HEAD']).decode().strip()
です. これは,
git rev-parse HEAD
のコマンドをターミナル上で実行した結果を反映しています.
関数冒頭1行は不要です.
def get_git_info(logger) -> logging.Logger:
logger = get_logger(cfg)
ご確認ありがとうございます.
def get_git_info(logger) -> logging.Logger:
git_info = "commit id: "
git_info += subprocess.check_output(
["git", "rev-parse", "HEAD"]
).decode().strip()
git_name = "username: "
git_name += subprocess.check_output(
["git", "config", "user.name"]
).decode().strip()
os_info = subprocess.check_output(["sw_vers"]).decode().strip()
logger.info(git_info)
logger.info(git_name)
logger.info(os_info)
return logger
訂正し, 実行環境の情報も追加してみたので,ご確認の程よろしくお願いいたします.
ありがとうございます. 確認が取れました.
OS の情報についても取得していただいているのですが, それはまた別途関数を用意してみましょう.
まずは GitHub の情報を取得するだけの get_git_info()
関数を実装し, commit しましょう.
かしこまりました. コミットが完了いたしました.
OKです.
それでは OS の情報を取得する get_os_info()
関数を同様に書いてみましょう.
先の GitHub の log と合わせて次のような出力をイメージしましょう.
2024-04-12 20:06:51,813 - experiment_tools.start_logging - INFO - commit id: 136d189e646e86d1fdba39d3bf3d615148fb6579
2024-04-12 20:06:51,814 - experiment_tools.start_logging - INFO - username: victor-von-pooh
2024-04-12 20:06:51,827 - experiment_tools.start_logging - INFO - OS infomation:
OS: Darwin 21.2.0
Processor: i386
Machine: x86_64
Node: akita
Python Version: 3.9.13
おすすめは platform ライブラリを使うことです.
お疲れ様です.
get_os_info()
関数を書いてみました.
引数のlogger
に,先ほどのget_git_info()
の返り値であるloggerを渡すイメージです.
ご確認の程よろしくお願いいたします.
def get_os_info(logger) -> logging.Logger:
os_info = "OS information: \n"
info_dict = {"OS": subprocess.check_output(platform.system_alias()),
"Processor": subprocess.check_output(platform.processor()),
"Machine": subprocess.check_output(platform.machine()),
"Node": subprocess.check_output(platform.node()),
"Python Version": subprocess.check_output(
platform.python_version())
}
for key, value in info_dict.items():
os_info += key
os_info += ": "
os_info += value
os_info += "\n"
logger.info(os_info)
return logger
platform.hogehoge()
はコマンドではないので subprocess.check_output()
の引数に入れる必要はないです.
ありがとうございます.
def get_os_info(logger) -> logging.Logger:
os_info = "OS infomation: "
info_dict = {"OS": platform.system_alias(),
"Processor": platform.processor(),
"Machine": platform.machine(),
"Node": platform.node(),
"Python Version": platform.python_version()
}
for key, value in info_dict.items():
os_info += key
os_info += ": "
os_info += value
logger.info(os_info)
return logger
で大丈夫でしょうか.
概形は悪くはないです. 数ヶ所直すと良いポイントがあります. 内容把握が出来たらチェックをつけてください.
info_dict
の書き方platform.system_alias()
には引数が必要for key, value in info_dict.items():
下でエラーが生じるinfo_dict
の書き方インデントの揃え方があまり良くないです. 基本的に, list や dict などでは, 次のようにします.
info_dict = {
"OS": platform.system_alias(),
"Processor": platform.processor(),
"Machine": platform.machine(),
"Node": platform.node(),
"Python Version": platform.python_version(),
}
インデントの位置は4つ刻みになるのが基本です. また, 最後の item にもカンマ( , )は打つと良いですね.
platform.system_alias()
には引数が必要こちらは次のような TypeError
が表示されてしまいます.
TypeError: system_alias() missing 3 required positional arguments: 'system', 'release', and 'version'
ここは普通に,
"OS": f"{platform.system()} {platform.release()}"
などとすると良いかと思います.
for key, value in info_dict.items():
下でエラーが生じるplatform.system_alias()
の返り値がタプルになるため, 型の不一致から os_info += value
ができなくなってしまいます.
def get_os_info(logger: logging.Logger) -> logging.Logger:
os_info = "\n\n"
spec = [
f"\tOS: {platform.system()} {platform.release()}",
f"\tProcessor: {platform.processor()}",
f"\tMachine: {platform.machine()}",
f"\tNode: {platform.node()}",
f"\tPython Version: {platform.python_version()}"
]
for item in spec:
os_info += item
os_info += "\n"
logger.info(f"OS infomation: {os_info}")
return logger
ありがとうございます.内容把握が完了いたしました.
加えてなのですが,configファイルがまだないため,実は挙動を確認できないまま,貼り付けてしまいました. 書いたプログラムを試すには,configファイルを仮作成すべきだったのでしょうか.
書いたプログラムを試すには,configファイルを仮作成すべきだったのでしょうか.
出来るようであればしておくと良いと思いますが, この後 config を実際に作って確認する工程に入るので, 今は無くても大丈夫です.
とりあえず, get_os_info()
関数を追記しましょう.
かしこまりました.コミットいたしました.
ありがとうございます.
確認が出来ました.
それでは最後のステップですが, 今までの実装プログラムを全て起動して log を作る start_experiment()
関数を tide/experiment_tools/set_up.py
ファイル内に実装してみましょう.
次のフレームワークを埋めてください. コメントアウトは消しても良いです.
def start_experiment(cfg: dict) -> logging.Logger:
# log の起動 ↓↓↓
# log の起動 ↑↑↑
# 乱数 seed の固定 ↓↓↓
# 乱数 seed の固定 ↑↑↑
# log に GitHub と OS の環境情報を入れる ↓↓↓
# log に GitHub と OS の環境情報を入れる ↑↑↑
return logger
お疲れ様です. 書いてみたので,ご確認の程よろしくお願いいたします.
def start_experiment(cfg: dict) -> logging.Logger:
logger = get_logger(cfg)
fix_seed(41)
logger = get_git_info(logger)
logger = get_os_info(logger)
return logger
@tottocoslowlifer ご対応ありがとうございます.
fix_seed(41)
こちらのみ引数を config の "seed"
で読み取れるようにしてください.
それ以外は OK なので tide/experiment_tools/set_up.py
に入れて commit してください.
ありがとうございます.
関数get_logger()
およびfix_seed()
は他のファイルで定義されている状態ですが,このままコミットして大丈夫でしょうか.
@tottocoslowlifer
関数get_logger()およびfix_seed()は他のファイルで定義されている状態ですが,このままコミットして大丈夫でしょうか.
このファイルで使えるように適切に追記してください.
かしこまりました.コミットが完了いたしました.
4月〜5月にかけて
機械学習のアルゴリズムを実装し, 潮位のデータを用いて未来の数値を予測する.
準備
実験を行う上での準備を整える手順を示す.
preprocessed_df
を作成し, 新たに csv ファイルを作成するスクリプトをtide/scripts
に用意する