- 投稿日:2020-08-23T23:44:49+09:00
macOS で pyenv install すると BUILD FAILED となり Python のインストールに失敗するときの解決法 (の一つ)
解決法
pyenv を使用して Python をインストールしたところ BUILD FAILED となりインストールに失敗しました。原因は binutils でした。binutils を一旦アンインストールしてから再実行したらうまくいきました。
$ brew uninstall binutils $ pyenv install <PYTHON_VERSION> $ brew install binutilsなぜ binutils がインストールされているとインストールに失敗するのかはよくわかりませんでした。
"pyenv install build failed macos" などで調べてみるとたくさん記事が出てくるのですが、どれも解決法がバラバラでした。自分の場合は binutils をアンインストールするだけで解決したので、解決法の一つとして共有しておきます。参考になれば幸いです。
環境
環境 バージョン macOS 10.15.6 pyenv 1.2.20-3-g58c776a1 Python (この手順でインストールしたもの) 3.8.5 その他のシステム情報 Brewfile.lock.json
- 投稿日:2020-08-23T23:01:56+09:00
Scapyのコードを少しみてみる。構造体をどう処理しているか。
目的
少し用事があり、例えば、Scapyのコードはどんな感じが見てみた。
Scapyとは、
Scapy is a powerful Python-based interactive packet manipulation program and library.
(引用:https://pypi.org/project/scapy/)Pythonには構造体がないので、
パケットなどの構造体的なデータをどう処理しているかを確認した。対象コードは、
https://github.com/secdev/scapy引用コードもすべて上記。
わかったこと
概要
コード上、以下の2つの構造体関連の処理があった
- structモジュール
- Structureクラス
基本、前者が使われている。
structモジュール
↓以下のような感じで、packしていた。
psdhdr = struct.pack("!4s4sHH", inet_pton(socket.AF_INET, u.src), inet_pton(socket.AF_INET, u.dst), proto, ln)Structureクラス
↓以下のようなコードがあるが、Windowsのpcap対応用??
使われ方がよくわからなかった。class sockaddr_in(Structure): _fields_ = [("sin_family", SHORT), ("sin_port", USHORT), ("sin_addr", in_addr), ("sin_zero", 8 * CHAR)]まとめ
有名なScapyで、パケットの構造体的なデータがどう処理されているかを確認した。
structモジュールが使われていた。
(上記、少し、語弊があります。データをかためる部分で、structモジュールが使われていたという言い方が適当かも。)
c言語等に構造体がどう扱われているかという意味では、かためる以外の部分は、普通にクラスのメンバーになっているという言い方が正しいと思う。コメントなどあれば、お願いします。
- 投稿日:2020-08-23T22:31:01+09:00
Spyderのアップデート方法
- 投稿日:2020-08-23T22:16:44+09:00
DeepMind製強化学習フレームワーク Acme
以前の記事で少し触れたDeepMind製の強化学習向けフレームワーク Acme (a research framework for reinforcement learning) についての紹介記事
(いつものように、自ブログに投稿した英語記事の日本語焼き直し。)
1. はじめに
DeepMindの研究者が実際に毎日のように使っている強化学習向けフレームワークのコード(の一部)をOSSとして公開したもの。
Acmeはシンプルな学習ループAPIを提供しており、ざっくりとは以下のようなコードになる。
学習ループloop = acme.EnvironmentLoop(environment, agent) loop.run()Acmeは、ネットワークとしてTensorFlow (※ 特定のnightlyビルドのみ)とJAXをサポートしている。
また、経験再生用に Reverb を利用してる。(拙著の解説記事1と解説記事2)
テクニカルレポートには、"Acme: A Research Framework for Distributed Reinforcement Learning" と分散強化学習だと表現されているが、FAQを読む限り、残念ながら分散学習のエージェントは公開されておらず、公開する時期も決まっていないらしい。
2. インストール
PyPIに "dm-acme" といパッケージ名で公開されている。
指定可能なオプションは、"jax", "tf", "envs", "reverb", "testing" の5つ。
個人的には、経験再生用の"reverb"は指定必須、"tf"または"jax"のどちらかひとつも必須だと考える。
特にTensorFlowは'tf-nightly==2.4.0.dev20200708'が指定してあったりと、環境の互換性など投げ捨てられているので、おとなしく綺麗な環境にAcmeのインストールオプションでインストールすることをおすすめする。"envs"は指定することで、"dm-control" や "gym" などの強化学習向け環境がインストールされる。("dm-control" は MuJoCoのライセンスが必要。)
インストールTensorFlow版pip install dm-acme[reverb,tf]インストールJAX版pip install dm-acme[reverb,jax]3. 環境
DeepMind Environment APIに準拠する環境を利用することができる。
gym.Envとの大きな違いは、step(action)等のメンバー関数が、tupleではなくdm_env.TimeStepという独自クラスを返すことである。TimeStepクラスでは、観測値や報酬などに加えて、ステップ(遷移)が、エピソードの最初(StepType.FIRST)、途中(StepType.MID)、最後(StepType.LAST)のどれであるかの情報も保持している。
gym.Env向けにacme.wrappers.GymWrapperが提供されており、ラップするだけでAcmeで使うことができるgym.Envの利用import acme import gym env = acme.wrappers.GymWrapper(gym.make("MountainCarContinuous-v0"))4. エージェント
実装済みのエージェントはこちらにある。
2020年8月現在、11個のエージェントが提供されている。
- 連続値制御
- Deep Deterministic Policy Gradient (DDPG)
- Distributed Distributional Deep Determinist (D4PG)
- Maximum a posteriori Policy Optimisation (MPO)
- Distributional Maximum a posteriori Policy Optimisation (DMPO)
- 離散値制御
- Deep Q-Networks (DQN)
- Importance-Weighted Actor-Learner Architectures (IMPALA)
- Recurrent Replay Distributed DQN (R2D2)
- Batch RL
- Behavior Cloning (BC)
- デモンストレーションからの学習
- Deep Q-Learning from Demonstrations (DQfD)
- Recurrent Replay Distributed DQN from Demonstratinos (R2D3)
- モデルベースRL
- Monte-Carlo Tree Search (MCTS)
これらの実装は
acme.agents.agent.Agentを拡張することで実装されているので、カスタムアルゴリズムを実装する際は、同様に拡張することで可能である(と思われる)。上の提供されているエージェントは、DeepMind製の深層学習ライブラリのSonnet (TensorFlow)またはHaiku (JAX)を利用している。そのため、(ざっと確認した限りでは)実装済みのエージェントの内部ネットワークを定義するためには、SonnetやHaikuで深層学習モデルを構築して渡すことが想定されている。(もちろんインターフェースには無関係なので、独自実装する際には関係ない。)
5. チュートリアル
Acmeはクイックスタート ノートブックを提供している。また、MuJoCoのライセンスを所持していれば、チュートリアル ノートブックも試すことができる。
6. おわりに
DeepMindが公開している強化学習用フレームワークのAcmeの概要を調査した。第一線級の企業が普段から利用しているコードと同じものが(一部とは言え)提供されており、今後の発展も含めて非常に興味深い。
ただし、TensorFlowのバージョンがnightlyのとあるビルドに固定されていたりと、一般的なユーザーが利用するには少し難があるようにも感じられる。
引き続き、状況をウォッチしていきたい。
余談
クイックスタートにスクラッチでコードが書いてあるような、Gym環境をノートブック上で表示するためのコードをパッケージ化してGym-Notebook-Wrapperとして提供しています。(解説記事)
こちらも興味を持っていただけたらぜひ使って見てください。
- 投稿日:2020-08-23T21:43:58+09:00
【python】東京と○○県の暑さを可視化(DataFrame使い方メモ)
0.日常に潜む問題
緊急事態宣言の中で迎える夏。
三密を徹底的に避けるために、遊びはおろか日頃から通ってアイデアを
もらっていたカフェにも行けず家に籠もっている。
話題といえば、コロナウィルスの感染者数と、暑さについてのみ。都内に住む私としては、暑くて身動きが取れない話をしても、従姉妹や父からも地元も同じくらい暑い、暑い中でこんな運動(サイクリング)をしているなどの話を聞かされ、勝手に暑さ競争をされているようで辟易していた。
時々見るニュースでは、雪国でしられる地元は東京と変わりない位の最高気温を叩き出しているように見える。
地面から湯気が立っているのではないかと思うぐらいの暑さで、
10分歩いただけでフラフラする。
そしてカフェに入って冷たいドリンクを飲んでも、体中に充満した熱は簡単に取れない状態だ。
ドリンクを飲みながら、新潟と東京の暑さを最高気温で比較する方法を考えてみた。1.気温データの取得
気象庁から下記の手順で各地域の気象情報を取得することができた。
今回は新潟と東京のデータが必要なので、下記を東京の場合でも
実施して「csvファイルをダウンロード」ボタンを押す。上記のcsvファイルの項目部分のみを使いやすいように編集した。
2.様々な課題
(1)CSVファイルを読み込む
weather_parse2.jpynbimport pandas as pd import datetime as dt #グラフを表示するライブラリ import matplotlib.pyplot as plt #日本語化のライブラリ import japanize_matplotlib #文字コードを指定して読み込む df = pd.read_csv("data_weather2.csv",encoding="sjis") print(df)出力結果
年月日 平均気温(℃)_東京 品質情報 均質番号 最高気温(℃)_東京 品質情報.1 均質番号.1 \ 0 2020/1/1 5.5 8 1 10.2 8 1 1 2020/1/2 6.2 8 1 11.3 8 1 2 2020/1/3 6.1 8 1 12.0 8 1 3 2020/1/4 7.2 8 1 12.2 8 1 4 2020/1/5 5.4 8 1 10.2 8 1 .. ... ... ... ... ... ... ... 229 2020/8/17 30.8 8 1 36.5 8 1 230 2020/8/18 30.3 8 1 34.3 8 1 231 2020/8/19 29.0 8 1 34.2 8 1 232 2020/8/20 29.7 8 1 34.8 8 1 233 2020/8/21 30.1 8 1 36.0 8 1 最低気温(℃)_東京 品質情報.2 均質番号.2 平均気温(℃)_新潟 品質情報.3 均質番号.3 最高気温(℃)_新潟 \ 0 3.2 8 1 3.6 8 1 5.6 1 1.9 8 1 3.0 8 1 5.7 2 1.4 8 1 4.2 8 1 6.9 3 3.6 8 1 5.5 8 1 8.3 4 0.6 8 1 4.2 8 1 7.2 .. ... ... ... ... ... ... ... 229 27.2 8 1 27.8 8 1 30.4 230 27.8 8 1 26.3 8 1 29.0 231 25.6 8 1 26.8 8 1 30.9 232 25.8 8 1 28.5 8 1 33.7 233 26.0 8 1 27.5 8 1 30.8 品質情報.4 均質番号.4 最低気温(℃)_新潟 品質情報.5 均質番号.5 0 8 1 1.0 8 1 1 8 1 2.0 8 1 2 8 1 1.7 8 1 3 8 1 2.4 8 1 4 8 1 1.7 8 1 .. ... ... ... ... ... 229 8 1 26.3 8 1 230 8 1 23.3 8 1 231 8 1 22.0 8 1 232 8 1 22.8 8 1 233 8 1 23.8 8 1 [234 rows x 19 columns](2)グラフ化する列の選択と範囲選択
(メモ1)上記から列名1と列名2を選んで表示するには
DataFrame[[‘列名1’,’列名2’]]と指定する。(メモ2)DataFrameの作成
DataFrame名=pd.DataFrame(データ,columns=指定したい列名のリスト)(メモ3)列名3をデフォルトの日付型(yyyy-mm-dd)に変換するには
DataFrame名['列名3'] = pd.to_datetime(DataFrame名['列名3'], format='列名3の変更前のフォーマット')weather_parse2.jpynbnew_columns = ['年月日', '最高気温(℃)_東京', '最高気温(℃)_新潟'] # カラム名 new_data=df[['年月日','最高気温(℃)_東京','最高気温(℃)_新潟']] #dataframe再作成 new_df=pd.DataFrame(new_data,columns=new_columns) #何もしない場合、日付タイプと認識されない print(new_df.dtypes) #年月日列を日付タイプに変換 new_df['年月日'] = pd.to_datetime(new_df['年月日'], format='%Y/%m/%d') print(new_df.dtypes) print(new_df)出力結果
年月日 object 最高気温(℃)_東京 float64 最高気温(℃)_新潟 float64 dtype: object 年月日 datetime64[ns] 最高気温(℃)_東京 float64 最高気温(℃)_新潟 float64 dtype: object 年月日 最高気温(℃)_東京 最高気温(℃)_新潟 0 2020-01-01 10.2 5.6 1 2020-01-02 11.3 5.7 2 2020-01-03 12.0 6.9 3 2020-01-04 12.2 8.3 4 2020-01-05 10.2 7.2 .. ... ... ... 229 2020-08-17 36.5 30.4 230 2020-08-18 34.3 29.0 231 2020-08-19 34.2 30.9 232 2020-08-20 34.8 33.7 233 2020-08-21 36.0 30.8 [234 rows x 3 columns]weather_parse2.jpynbnew_df2=new_df[(new_df['年月日'] >= dt.datetime(2020,8,1)) & (new_df['年月日'] < dt.datetime(2020,8,21))] print(new_df2)出力結果
年月日 最高気温(℃)_東京 最高気温(℃)_新潟 213 2020-08-01 31.8 28.8 214 2020-08-02 31.5 30.3 215 2020-08-03 32.3 32.2 216 2020-08-04 33.1 32.7 217 2020-08-05 34.2 33.4 218 2020-08-06 33.1 33.6 219 2020-08-07 35.4 28.3 220 2020-08-08 32.3 24.8 221 2020-08-09 34.7 28.4 222 2020-08-10 35.2 35.6 223 2020-08-11 37.3 35.7 224 2020-08-12 35.8 31.4 225 2020-08-13 36.1 31.4 226 2020-08-14 34.2 32.0 227 2020-08-15 36.1 30.1 228 2020-08-16 35.4 31.4 229 2020-08-17 36.5 30.4 230 2020-08-18 34.3 29.0 231 2020-08-19 34.2 30.9 232 2020-08-20 34.8 33.7
- 年月日がyyyy-mm-dd表示になっている。
(3)グラフ化
weather_parse2.jpynb#グラフ化したいデータを指定 new_columns3 = ['最高気温(℃)_東京', '最高気温(℃)_新潟'] # カラム名 new_data3=new_df2[['最高気温(℃)_東京','最高気温(℃)_新潟']] new_df3=pd.DataFrame(new_data3,columns=new_columns3) #グラフ表示 new_df3.plot()
- 横軸のインデックス値が行数になっているので、日付に対する温度の対応がわからない。
- グラフが折れ線になっていて、比較がしにくい
3.完成形(インデックスを日付に指定して、指定した期間の最高気温を出力する)
weather_parse3.jpynbimport pandas as pd import datetime as dt #グラフを表示するライブラリ import matplotlib.pyplot as plt #日本語化のライブラリ import japanize_matplotlib #文字コードを指定して読み込む、年月日をインデックスに df = pd.read_csv("data_weather2.csv",encoding="sjis") #年月日をインデックスに df.index=pd.to_datetime(df['年月日'], format='%Y/%m/%d').values #もともとの列を削除 df = df.drop(columns='年月日') print(df)出力結果
- インデックスが日付型になっている。
平均気温(℃)_東京 品質情報 均質番号 最高気温(℃)_東京 品質情報.1 均質番号.1 最低気温(℃)_東京 \ 2020-01-01 5.5 8 1 10.2 8 1 3.2 2020-01-02 6.2 8 1 11.3 8 1 1.9 2020-01-03 6.1 8 1 12.0 8 1 1.4 2020-01-04 7.2 8 1 12.2 8 1 3.6 2020-01-05 5.4 8 1 10.2 8 1 0.6 ... ... ... ... ... ... ... ... 2020-08-17 30.8 8 1 36.5 8 1 27.2 2020-08-18 30.3 8 1 34.3 8 1 27.8 2020-08-19 29.0 8 1 34.2 8 1 25.6 2020-08-20 29.7 8 1 34.8 8 1 25.8 2020-08-21 30.1 8 1 36.0 8 1 26.0 品質情報.2 均質番号.2 平均気温(℃)_新潟 品質情報.3 均質番号.3 最高気温(℃)_新潟 品質情報.4 \ 2020-01-01 8 1 3.6 8 1 5.6 8 2020-01-02 8 1 3.0 8 1 5.7 8 2020-01-03 8 1 4.2 8 1 6.9 8 2020-01-04 8 1 5.5 8 1 8.3 8 2020-01-05 8 1 4.2 8 1 7.2 8 ... ... ... ... ... ... ... ... 2020-08-17 8 1 27.8 8 1 30.4 8 2020-08-18 8 1 26.3 8 1 29.0 8 2020-08-19 8 1 26.8 8 1 30.9 8 2020-08-20 8 1 28.5 8 1 33.7 8 2020-08-21 8 1 27.5 8 1 30.8 8 均質番号.4 最低気温(℃)_新潟 品質情報.5 均質番号.5 2020-01-01 1 1.0 8 1 2020-01-02 1 2.0 8 1 2020-01-03 1 1.7 8 1 2020-01-04 1 2.4 8 1 2020-01-05 1 1.7 8 1 ... ... ... ... ... 2020-08-17 1 26.3 8 1 2020-08-18 1 23.3 8 1 2020-08-19 1 22.0 8 1 2020-08-20 1 22.8 8 1 2020-08-21 1 23.8 8 1 [234 rows x 18 columns]weather_parse3.jpynb#列の切り出し new_columns = ['最高気温(℃)_東京', '最高気温(℃)_新潟'] # カラム名 new_data=df[['最高気温(℃)_東京','最高気温(℃)_新潟']] #dataframe再作成 new_df=pd.DataFrame(new_data,columns=new_columns) print(new_df)出力結果
最高気温(℃)_東京 最高気温(℃)_新潟 2020-01-01 10.2 5.6 2020-01-02 11.3 5.7 2020-01-03 12.0 6.9 2020-01-04 12.2 8.3 2020-01-05 10.2 7.2 ... ... ... 2020-08-17 36.5 30.4 2020-08-18 34.3 29.0 2020-08-19 34.2 30.9 2020-08-20 34.8 33.7 2020-08-21 36.0 30.8 [234 rows x 2 columns]weather_parse3.jpynbnew_df2=new_df['2020-08-01':'2020-08-21'] print(new_df2)出力結果
最高気温(℃)_東京 最高気温(℃)_新潟 2020-08-01 31.8 28.8 2020-08-02 31.5 30.3 2020-08-03 32.3 32.2 2020-08-04 33.1 32.7 2020-08-05 34.2 33.4 2020-08-06 33.1 33.6 2020-08-07 35.4 28.3 2020-08-08 32.3 24.8 2020-08-09 34.7 28.4 2020-08-10 35.2 35.6 2020-08-11 37.3 35.7 2020-08-12 35.8 31.4 2020-08-13 36.1 31.4 2020-08-14 34.2 32.0 2020-08-15 36.1 30.1 2020-08-16 35.4 31.4 2020-08-17 36.5 30.4 2020-08-18 34.3 29.0 2020-08-19 34.2 30.9 2020-08-20 34.8 33.7 2020-08-21 36.0 30.8weather_parse3.jpynbcolorlist=["red","blue"] #指定した色で棒グラフ表示 new_df2.plot.bar(color=colorlist) #凡例の表示位置を右下に指定 plt.legend(loc="lower right") plt.show()出力結果
結論
最高気温は、東京の方が高い日が多い。
- 投稿日:2020-08-23T21:41:36+09:00
[AWS] Lambda関数のユニットテストをローカル環境で実行してみよう
前提
今回は、以下のような前提で検証してみたいと思います。
- SAM
- Lambda
- Python3.8
- pytest
- moto(モック)
- DynamoDB
なお、SAMを使用すると、Dockerん環境を使って擬似的にローカル環境にDynamoDBなどを構築することができますが、今回は、ユニットテスト(将来的な自動テスト)を見据えてのテストについて検証してみたいと思います。
プロジェクト作成
では、まず最初にプロジェクトを作成します。
もし、SAMでのプロジェクト作成がよくわからない方は、事前に
- [AWS] Serverless Application Model (SAM) の基本まとめ
- [AWS] Serverless Application Model (SAM) でAPI Gateway + Lambda + DynamoDBなサンプルを作成してみる
に目を通されることをおすすめします。
$ sam init --runtime=python3.8 Which template source would you like to use? 1 - AWS Quick Start Templates 2 - Custom Template Location Choice: 1 Project name [sam-app]: Cloning app templates from https://github.com/awslabs/aws-sam-cli-app-templates.git AWS quick start application templates: 1 - Hello World Example 2 - EventBridge Hello World 3 - EventBridge App from scratch (100+ Event Schemas) 4 - Step Functions Sample App (Stock Trader) 5 - Elastic File System Sample App Template selection: 1 ----------------------- Generating application: ----------------------- Name: sam-app Runtime: python3.8 Dependency Manager: pip Application Template: hello-world Output Directory: . Next steps can be found in the README file at ./sam-app/README.md必要なパッケージのインストール
ユニットテストを実行するために必要なPythonのパッケージをインストールします。
$ pipenv install pytest pytest-mock mocker moto --devユニットテスト
以下のコマンドで、Lamnda関数を呼び出して、各Lambda関数のユニットテストを実行できます。
まずは、デフォルトで作成されているHelloWorldのLambda関数のテスト(こちらのテストコードもデフォルトで作成済み)を実行してみましょう。$ python -m pytest tests ============================= test session starts ============================== platform darwin -- Python 3.8.5, pytest-6.0.1, py-1.9.0, pluggy-0.13.1 rootdir: /Users/******/aws/github/sam-app plugins: mock-3.3.0 collected 1 item tests/unit/test_handler.py . [100%] ============================== 1 passed in 0.02s ===============================1件のテストが成功したことがわかります。
DynamoDBアクセスコードの追加
今回は、ユニットテストすることだけを目的とするため、特にSAMの設定変更等は行わずに、テストに必要な変更のみを行うようにします。
では、DynamoDBにアクセス(レコード追加)する処理の追加を行ってみます。hello_world/app.pyimport json import boto3 import os from datetime import datetime def lambda_handler(event, context): try: event_body = json.loads(event["body"]) dynamodb = boto3.resource("dynamodb") table = dynamodb.Table("Demo") table.put_item( Item={ "Key": event_body["test"], "CreateDate": datetime.utcnow().isoformat() } ) return { "statusCode": 200, "body": json.dumps({ "message": "hello world", }), } except Exception as e: return { "statusCode": 500, "body": json.dumps({ "message": e.args }), }テストコードに、DynamoDBのモックアップを追加
tests/unit/test_handler.pyimport boto3 import json import pytest from hello_world import app from moto import mock_dynamodb2 @pytest.fixture() def apigw_event(): """ Generates API GW Event""" return { "body": '{ "test": "body"}', "resource": "/{proxy+}", "requestContext": { "resourceId": "123456", "apiId": "1234567890", "resourcePath": "/{proxy+}", "httpMethod": "POST", "requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef", "accountId": "123456789012", "identity": { "apiKey": "", "userArn": "", "cognitoAuthenticationType": "", "caller": "", "userAgent": "Custom User Agent String", "user": "", "cognitoIdentityPoolId": "", "cognitoIdentityId": "", "cognitoAuthenticationProvider": "", "sourceIp": "127.0.0.1", "accountId": "", }, "stage": "prod", }, "queryStringParameters": {"foo": "bar"}, "headers": { "Via": "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)", "Accept-Language": "en-US,en;q=0.8", "CloudFront-Is-Desktop-Viewer": "true", "CloudFront-Is-SmartTV-Viewer": "false", "CloudFront-Is-Mobile-Viewer": "false", "X-Forwarded-For": "127.0.0.1, 127.0.0.2", "CloudFront-Viewer-Country": "US", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", "Upgrade-Insecure-Requests": "1", "X-Forwarded-Port": "443", "Host": "1234567890.execute-api.us-east-1.amazonaws.com", "X-Forwarded-Proto": "https", "X-Amz-Cf-Id": "aaaaaaaaaae3VYQb9jd-nvCd-de396Uhbp027Y2JvkCPNLmGJHqlaA==", "CloudFront-Is-Tablet-Viewer": "false", "Cache-Control": "max-age=0", "User-Agent": "Custom User Agent String", "CloudFront-Forwarded-Proto": "https", "Accept-Encoding": "gzip, deflate, sdch", }, "pathParameters": {"proxy": "/examplepath"}, "httpMethod": "POST", "stageVariables": {"baz": "qux"}, "path": "/examplepath", } @mock_dynamodb2 def test_lambda_handler(apigw_event, mocker): dynamodb = boto3.resource('dynamodb') dynamodb.create_table( TableName='Demo', KeySchema=[ { 'AttributeName': 'Key', 'KeyType': 'HASH' }, { 'AttributeName': 'CreateDate', 'KeyType': 'RANGE' } ], AttributeDefinitions=[ { 'AttributeName': 'Key', 'AttributeType': 'S' }, { 'AttributeName': 'CreateDate', 'AttributeType': 'S' } ], ProvisionedThroughput={ 'ReadCapacityUnits': 10, 'WriteCapacityUnits': 10 } ) ret = app.lambda_handler(apigw_event, "") data = json.loads(ret["body"]) assert ret["statusCode"] == 200 assert "message" in ret["body"] assert data["message"] == "hello world" # assert "location" in data.dict_keys()主な修正点は、
- importに必要な定義追加
test_lambda_handler前に@mock_dynamodb2追加test_lambda_handlerで、Lambda関数呼び出し前に擬似的にDynamoDBのテーブル作成です。
ユニットテスト実行
では、早速ユニットテストを実行してみます。
$ python -m pytest tests ============================= test session starts ============================== platform darwin -- Python 3.8.5, pytest-6.0.1, py-1.9.0, pluggy-0.13.1 rootdir: /Users/******/aws/github/sam-app plugins: mock-3.3.0 collected 1 item tests/unit/test_handler.py . [100%] =============================== warnings summary =============================== [pytest] /Users/******/.local/share/virtualenvs/sam-app-3Tr4jFKA/lib/python3.8/site-packages/boto/plugin.py:40 /Users/******/.local/share/virtualenvs/sam-app-3Tr4jFKA/lib/python3.8/site-packages/boto/plugin.py:40: DeprecationWarning: the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses import imp /Users/******/.local/share/virtualenvs/sam-app-3Tr4jFKA/lib/python3.8/site-packages/moto/cloudformation/parsing.py:407 /Users/******/.local/share/virtualenvs/sam-app-3Tr4jFKA/lib/python3.8/site-packages/moto/cloudformation/parsing.py:407: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated since Python 3.3, and in 3.9 it will stop working class ResourceMap(collections.Mapping): -- Docs: https://docs.pytest.org/en/stable/warnings.html一応、成功していますが、警告が出ています。
これは、現在のPythonのバージョンでは、motoなどで使用している一部機能が使用停止されていることを表しています。
今回のユニットテストには影響のない警告なので、プロジェクトのホームにpytest.iniという名称でファイルを作成し、以下を記述して保存してみましょう。pytest.ini[pytest] filterwarnings = ignore::DeprecationWarningでは、再度実行してみましょう。
$ python -m pytest tests ============================= test session starts ============================== platform darwin -- Python 3.8.5, pytest-6.0.1, py-1.9.0, pluggy-0.13.1 rootdir: /Users/******/aws/github/sam-app, configfile: pytest.ini plugins: mock-3.3.0 collected 1 item tests/unit/test_handler.py . [100%] ============================== 1 passed in 2.10s ===============================今度は警告なく終了しました。
まとめ
ユニットテストは、ソースコード変更時に自動実行されることが望ましいです。
今回は、ユニットテストの実行をローカルで行っているため、ソースコード部分のみの修正に留めていますが、CI/CDのパイプラインの延長で行う場合は、requirements.txtや各定義ファイルにも修正が必要です。
次回は、その辺のパイプラインとの結合も含めた検証を、どこかのタイミングでやってみたいと思います。サンプルコードリポジトリ
- 投稿日:2020-08-23T19:39:37+09:00
GCPでJupyterLabを使ってBigQueryのデータを可視化してみた
注意
私はGCPもpythonもjupyterも初心者です。ぐぐりながら動かせてとても嬉しかったので投稿させていただきました。
間違いなどありましたら教えていただけるとありがたいです。参考
BigQueryのデータを作っておく
GCPのコンソールを開く
https://console.cloud.google.com/
サイドメニューの「BigQuery」を選択
「データセットを作成」をクリック
データセットIDを「test_data_set」にして作成してみました
テスト用にテーブルとデータを簡単に作成
以下のクエリをクエリエディタに貼って実行をクリック
create table test_data_set.t (i INT64); insert into test_data_set.t values (1),(2),(5),(7),(12);データができたので、こちらをJupyterを使って見てみようと思います。
ノートブックのインスタンス作成
サイドメニュー > 「API Platform」 > 「ノートブック」 を選択する
「新しいインスタンス」 > 「Python 2 and 3 」 を選択しました
リージョンなどが選択でき、見積もり金額も表示されるのですが、今回は試したらすぐインスタンスを削除するのでデフォルトの設定のままで「作成」を押しました
「JUPYTERLAB を開く」をクリック
JupyterLabが開く
最初bigqueryのデータを取得しようとした時に、
"UserWarning: Cannot create BigQuery Storage client, the dependency google-cloud-bigquery-storage is not installed."とエラーになったので先に
google-cloud-bigquery-storageをインストールしておく「コンソール」をクリック
google-cloud-bigquery-storageをインストールする$ pip install google-cloud-bigquery-storage
Python3を押して新しいノートブックを作成
JupyterLabのデフォルトで
/tutorials/bigquery/BigQuery basics.ipynbと言うファイルがありわかりやすい説明もありましたので、その辺を参考に簡単にbigqueryからのデータ取得の処理を作成してみましたfrom google.cloud import bigquery client = bigquery.Client(location="US") query = """ select * from test_data_set.t order by i """ query_job = client.query( query, # Location must match that of the dataset(s) referenced in the query. location="US", ) # API request - starts the query dv = query_job.to_dataframe() print(df) df.plot()「▷」を押して実行
最初に作ったbigqueryのデータをグラフ表示することができました!
最後に料金がかかるので、「停止」で停止しておく
最後まで見ていただいてありがとうございましたm(_ _)m
- 投稿日:2020-08-23T19:17:26+09:00
[python]pdf からテキストを抽出して、Open-Jtalkで文字を読み上げる
PDFのテキストを抽出する
PythonのpdfminerでPDFのテキストを抽出する方法を現役エンジニアが解説【初心者向け】$pip install pdfminer.sixfrom pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter from pdfminer.converter import TextConverter from pdfminer.layout import LAParams from pdfminer.pdfpage import PDFPage input_path = '抽出したPDFのパス' output_path = 'result.txt' manager = PDFResourceManager() with open(output_path, "wb") as output: with open(input_path, 'rb') as input: with TextConverter(manager, output, codec='utf-8', laparams=LAParams()) as conv: interpreter = PDFPageInterpreter(manager, conv) for page in PDFPage.get_pages(input): interpreter.process_page(page)Open JTalkのインストール
Pythonで音声を操作する方法
Pythonでテキストを読み上げる方法
以上2つのサイトを参考にさせて頂きました(というかほぼそのままです...)ありがとうございます。Open JTalkのversionを1.11に書き換えました。
より人間っぽく読み上げるには以下のような記事を参考にすると良さそうです。
読み上げBotが感情を持ちました
- 投稿日:2020-08-23T18:58:09+09:00
send_keysが動作しないとき
1 この記事は
スクレイピングライブラリーSeleniumにて、Webブラウザ上のテキストBOXに文字の入力を行うときに、サイトによっては所望の文字が入力できなかったり入力速度が遅くなったりします。その対応法です。
2 解決法
アカウントログイン画面にてログインを行う場面です。アカウントを自動入力する場合
send_keysでは、下記のコードを使います。test.pyID="abcdefg" elem_username = browser.find_element_by_name('loginid') elem_username.send_keys(ID)しかしながら、は所望の文字が入力できなかったり入力速度が遅くなる場合は、execute_scriptを使用すると解決します。
test.pyID="abcdefg" browser.execute_script('document.getElementsByName("loginid")[0].value="%s";' % ID)
- 投稿日:2020-08-23T18:54:33+09:00
Scapyのコードを少しみてみる。特殊メソッド__div__, __getitem__ とかのオーバロード。
目的
少し用事があり、例えば、Scapyのコードはどんな感じが見てみた。
Scapyとは、
Scapy is a powerful Python-based interactive packet manipulation program and library.
(引用:https://pypi.org/project/scapy/)Pythonの素人?(詳しくない意)の、ワタシには、かなり難しいコードでした。
まず、特殊メソッドのオーバロードあたりで、コードが
理解できなくなったので、わかったことをこの記事のメモにする。わかったこと
引用コードは、すべて、
https://github.com/secdev/scapy
から。__div__ のオーバロード
使い方:
a = IP(dst=dest) / TCP(flags="S", seq=i, sport=65000, dport=55556) b = IP(dst=dest)/ICMP()作用:
オブジェクトを「/」で、くっつける。以下のような感じのコードでオーバロードされている。
def __div__(self, other): if isinstance(other, Packet): cloneA = self.copy() cloneB = other.copy() cloneA.add_payload(cloneB) return cloneA elif isinstance(other, (bytes, str)): return self / conf.raw_layer(load=other) else: return other.__rdiv__(self)__getitem__のオーバロード
使い方:
seq = pkt[TCP].seq作用:
[ ]で、一部を取り出す。以下のような感じのコードでオーバロードされている。
def __getitem__(self, cls): if isinstance(cls, slice): lname = cls.start if cls.stop: ret = self.getlayer(cls.start, nb=cls.stop, **(cls.step or {})) else: ret = self.getlayer(cls.start, **(cls.step or {})) else: lname = cls ret = self.getlayer(cls) if ret is None: if isinstance(lname, Packet_metaclass): lname = lname.__name__ elif not isinstance(lname, bytes): lname = repr(lname) raise IndexError("Layer [%s] not found" % lname) return retまとめ
上記のオーバーロードは、便利に見えるので、他のモジュールとかでも使われているかも。
役立つかもしれない情報は、以下。
- a[iii] のメソッド名は、 __getitem__ です。
コメントなどあれば、お願いします。
この程度の処理は、他の言語でも沢山あるのかも。。Cぐらいしかわかっていないワタシには、基本的な記号(オペレータ)がオーバロードされると、多少、戸惑う。
- 投稿日:2020-08-23T18:25:04+09:00
venvでjupyterを使うためのkernel追加と削除
jupyterでvenvの環境を認識させるにはkerelを追加する必要があります。
※ちなみにjupyterはvenvごとにインストールする必要はないです。追加(my_venv) C:\> pip install ipykernel (my_venv) C:\> ipython kernel install --user --name=my_venv追加したらjupyternote bookの[Kernel]タブのChange kernelから選べばできる
削除C:\> jupyter kernelspec uninstall my_venv使わなくなった時に削除しないと永遠に残ります。
- 投稿日:2020-08-23T18:22:24+09:00
2. Pythonで綴る多変量解析 8-2. k近傍法 [ウェイトのかけ方] [回帰モデル]
- k近傍法は、予測に使用される重み関数(ウェイトのかけ方)が2通りあります。
- uniform : 一様な重みで、近傍のすべての点が等しく重みづけされます。
- distance : 点を距離の逆数で重みづけします。従って、近い点の方が、遠い点よりも大きな影響力を持ちます。
- デフォルトは uniform なので、distanceとするにはインスタンス生成時に引数で渡してやる必要があります。
これらの違いが、どのように予測結果に影響してくるのでしょうか。
前回の分類モデルのケースを例として示します。
- 境界が微妙に異なりますが、特に赤い○囲みの箇所に明らかな違いが見られます。
- 概してdistanceの方が、よりデータに対して忠実に境界が分けられています。
さらに、回帰モデルのケースで比較してみたいと思います。
⑴ ライブラリのインポート
import numpy as np import pandas as pd # scikit-learn系ライブラリ from sklearn.datasets import load_boston # ボストン住宅価格のデータセット from sklearn.model_selection import train_test_split # データ分割ユーティリティ from sklearn.neighbors import KNeighborsRegressor # k-NR回帰モデルのメソッド # 可視化ライブラリ import matplotlib.pyplot as plt import seaborn as sns # matplotlibの日本語表示モジュール !pip install japanize-matplotlib import japanize_matplotlib
- k近傍法は、主に分類モデルとしてk-NN(k-Nearest Neighbor)の名で通っていますが、scikit-learnのneighborsモジュールで回帰モデルはKNeighborsRegressorメソッドになります。
1. データを準備する
- scikit-learnのデータセットから「ボストン」を取得します。
- 米マサチューセッツ州北東部にある大都市ボストンの「住宅価格」を目的変数として、犯罪率や一戸当たり平均室数、交通アクセスなど13の属性情報を説明変数とする全506サンプルのデータセットです。
⑵ データの取得と整理
# データセットを取得 boston = load_boston() # 説明変数をDataFrameに変換 df = pd.DataFrame(boston.data, columns=boston.feature_names) # 目的変数を連結 df = pd.concat([df, pd.DataFrame(boston.target, columns=['MEDV'])], axis=1) print(df)
- 最右列「MEDV」は median value の略で、「1000ドル台の持家の中央値」と定義される目的変数(住宅価格)に当たります。
- 最左列「CRIM(crime rate):犯罪率」から「LSTAT(lower status):下層階級比率」まで、説明変数は全部で13ありますが、話を簡単にするために1変数のみ選び出すことにします。
⑶ 相関行列による分析軸の検討
- 全変数間の相関行列を作成し、住宅価格と相関の高い変数に注目します。
# 相関行列を作成 correlation_matrix = np.corrcoef(df.T) # 行・列ラベル names = ['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD', 'TAX', 'PTRATIO', 'B', 'LSTAT', 'MEDV'] # 相関行列をDataFrameに変換 correlation_df = pd.DataFrame(correlation_matrix, columns = names, index = names) # ヒートマップを描画 plt.figure(figsize=(10,8)) sns.heatmap(correlation_df, annot=True, cmap='coolwarm')
- 相関行列にはNumpyの
corrcoef()関数を使いますが、渡すデータを.Tで行と列を転置することにより変数間の相関を算出させます。- ヒートマップには seaborn を利用しています。
heatmap()の引数annot=Trueは、図中のセル毎に値を表示させます。
- 住宅価格(MEDV)と強い相関を示す変数としては、「下層階級比率(LSTAT)」が-0.74で強い負の相関を示し、また「一戸当たり平均室数(RM)」が0.70で強い正の相関を示しています。
- たいてい部屋数が多くなれば価格は高くなりますし、低所得層が多い地域であれば相場価格は低いということでしょう。シンプルに「一戸当たりの平均室数(RM)」を採用することにします。
⑷ データの抽出と分割
# 2変数のみ抽出 df_extraction = df[['RM', 'MEDV']] # 変数X, yを設定 X = np.array(df_extraction['RM']) y = np.array(df_extraction['MEDV']) X = X.reshape(len(X), 1) # 2次元に変換 y = y.reshape(len(y), 1) # 訓練・テストにデータ分割 X_train, X_test, y_train, y_test = train_test_split(X, y, random_state = 0) X_train = X_train.reshape(len(X_train), 1) # 2次元に変換 X_test = X_test.reshape(len(X_test), 1) y_train = y_train.reshape(len(y_train), 1) y_test = y_test.reshape(len(y_test), 1)
- 説明変数
RMと目的変数MEDVのみを抽出し、それぞれ変数Xとyとして訓練用・テスト用に分割します。2. kパラメータの検討
⑸ kパラメータを変更しながらk-NRを実行
- kを1~20個まで変更しながらk-NRを実行し、訓練データとテストデータの正解率の変化を観察します。
# 正解率を格納する変数 train_accuracy = [] test_accuracy = [] for k in range(1,21): kNR = KNeighborsRegressor(n_neighbors = k) # インスタンス生成 kNR.fit(X_train, y_train) # 学習 train_accuracy.append(kNR.score(X_train, y_train)) # 訓練の正解率 test_accuracy.append(kNR.score(X_test, y_test)) # テストの正解率 # 正解率をarrayに変換 training_accuracy = np.array(train_accuracy) test_accuracy = np.array(test_accuracy)⑹ 最適なkパラメータを選択
- 訓練とテストの正解率の変化を可視化し、併せて正解率の差分をグラフに示します。
# 訓練・テストの正解率の推移 plt.figure(figsize=(6, 4)) plt.plot(range(1,21), train_accuracy, label='訓練') plt.plot(range(1,21), test_accuracy, label='テスト') plt.xticks(np.arange(0, 21, 1)) # x軸目盛 plt.xlabel('k個数') plt.ylabel('正解率') plt.title('正解率の推移') plt.grid() plt.legend() # 正解率の差分の推移 plt.figure(figsize=(6, 4)) difference = np.abs(train_accuracy - test_accuracy) # 差分を計算 plt.plot(range(1,21), difference, label='差分') plt.xticks(np.arange(0, 21, 1)) # x軸目盛 plt.xlabel('k個数') plt.ylabel('差分(train - test)') plt.title('正解率の差分の推移') plt.grid() plt.legend() plt.show()
- kが増えるにつれて訓練の正解率は減少し、逆にテストの方は増加していますが、どちらもk=9くらいからほぼ横ばいとなっています。
- 差分をみると、順次k=14までは減少傾向にあることから、k=14を採用することにします。
3. モデルの実行と評価
- 予測に用いるダミーデータを作成します。
⑺ ダミーデータを作成
# 等差数列を生成 t = np.linspace(1, 10, 1000) # 開始値, 終了値, 要素数 # 2次元に形状を変換 T = t.reshape(1000, 1)⑻ 回帰モデルの実行と可視化
n_neighbors = 14 plt.figure(figsize=(12,5)) for i, w in enumerate(['uniform', 'distance']): model = KNeighborsRegressor(n_neighbors, weights=w) model = model.fit(X, y) y_ = model.predict(T) plt.subplot(1, 2, i + 1) plt.scatter(X, y, color='limegreen', label='データ') plt.plot(T, y_, color='navy', lw=1, label='予測値') plt.legend() plt.title("weights = '%s'" % (w)) plt.tight_layout() plt.show()
tight_layout()は、サブプロットのパラメータ(軸目盛、軸ラベル、タイトルの範囲)を自動的に調整して、サブプロットがグラフの領域内にぴったりと収まるようにしてくれます。
- まず一見してわかるのが、distanceの方は予測値の変動が著しく、データにオーバーフィッティング(過学習)しています。
- これに対して uniform の方は情報の要約ができており、デフォルトが uniform だというのも頷ける結果となりました。
- 投稿日:2020-08-23T18:18:58+09:00
犬ですが何か?Djangoアプリ作成開始の巻-- startapp
アプリケーションを作成する
暑くて散歩がつらい柴犬のぽん太です。今日は散歩中に川に飛び込んで水浴びをしたら飼い主に嫌がられました。
では、Djangoのアプリケーションを作りたいと思います。
(venv_dog) Ponta@shiba_app # tree . ├── db.sqlite3 ├── manage.py └── shiba_app ├── __init__.py ├── __pycache__ │ ├── __init__.cpython-38.pyc │ ├── settings.cpython-38.pyc │ ├── urls.cpython-38.pyc │ └── wsgi.cpython-38.pyc ├── asgi.py ├── settings.py ├── urls.py └── wsgi.py 2 directories, 11 files今日はここから始めます。
あれ、なんかディレクトリ(__pycache__)とファイルが増えていますね。
よくわからないのでとりあえずほっときます。
アプリケーションwanを作成します。
コマンドは
"python manage.py startalp (アプリケーション名)"
です。(venv_dog) Ponta@shiba_app # python manage.py startapp wan (venv_dog) Ponta@shiba_app # tree . ├── db.sqlite3 ├── manage.py ├── shiba_app │ ├── __init__.py │ ├── __pycache__ │ │ ├── __init__.cpython-38.pyc │ │ ├── settings.cpython-38.pyc │ │ ├── urls.cpython-38.pyc │ │ └── wsgi.cpython-38.pyc │ ├── asgi.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py └── wan ├── __init__.py ├── admin.py ├── apps.py ├── migrations │ └── __init__.py ├── models.py ├── tests.py └── views.py 4 directories, 18 filesディレクトリwanとその中にファイルができました。
次に何か表示をさせてみることにします。
views.pyに表示させる内容を書いてみますが、その前にviews.pyを覗いてみます。(venv_dog) Ponta@shiba_app # cat wan/views.py from django.shortcuts import render # Create your views here. (venv_dog) Ponta@shiba_app #次のように書きました。
(venv_dog) Ponta@shiba_app # cat wan/views.py from django.shortcuts import render from django.http import HttpResponse def index(request): return HttpResponse("Wan! 柴犬ぽん太") (venv_dog) Ponta@shiba_app #では、この関数httpアクセスによってこの関数を呼び出すように設定します。
shiba_app/urls.pyから直接呼び出してもいいのですが、wanというアプリケーションを作ったので、wan/urls.pyから呼び出すようにしたいと思います。(venv_dog) Ponta@shiba_app # cat shiba_app/urls.py from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('wan/', include('wan.urls')), ] (venv_dog) Ponta@shiba_app # cat wan/urls.py from django.urls import path from . import views urlpatterns = [ path('', views.index, name='index'), ] (venv_dog) Ponta@shiba_app #これでOKです。
http://127.0.0.1:8000/wan
にアクセスすると、shiba_app/urls.pyのurlpatternsの2行目、
path('wan/', include('wan.urls'))
でアプリケーションwanのディレクトリwanに転送され、次に、
wan/urls.pyのurlpatternsの
path('', views.index, name='index')
でviews.pyに記述している関数indexが呼び出されるはずです。テストサーバーを起動してアクセスしてみる
ではやってみましょう。まずはテストサーバーを起動します。
(venv_dog) Ponta@shiba_app # python manage.py runserver Watching for file changes with StatReloader Performing system checks... System check identified no issues (0 silenced). You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions. Run 'python manage.py migrate' to apply them. August 23, 2020 - 08:59:15 Django version 3.1, using settings 'shiba_app.settings' Starting development server at http://127.0.0.1:8000/ Quit the server with CONTROL-C.ブラウザでhttp://127.0.0.1:8000/wan/にアクセスします。
ちゃんと表示されたワン!成功だワン!
ちなみにターミナルの方では次のように表示されています、[23/Aug/2020 09:15:36] "GET /wan/ HTTP/1.1" 200 20HTTPステータスコード200(OK)が返されています。
ではまたね!バイバイ!
- 投稿日:2020-08-23T17:58:56+09:00
【Pythonコーディング規約】PEP 8 vs Google Style
はじめに
Pythonのコーディング規約として有名なのは標準ライブラリのコード規約PEP 8であるが、Google Python Style Guideというものがあるという。そこでGoogle StyleはPEP 8とどこが違うのかをまとめてみた。結論から言うとほとんどPEP 8と同じだったので、共通している規約(特に空行・空白関係)は割愛した。違いがあるのに網羅しきれてないところがあるかもしれないがご容赦頂きたい。
注
- 両者日本語訳が出ているが最新でない可能性があるので、極力英語版を参考にした
- PEP 8はpublic domain, Google Style GuideはCC by 3.0
比較表
項目 PEP8 複数の文を1行で書くこと 原則やめるべき if foo: bar(foo)はelseを伴わなければOK。それ以外はNG。;も使うな。1行の最大長 79文字 80文字 1行の最大長の例外 チームの合意があれば99文字でも良い、いずれにしろコメント行は72文字 import文、URL、パス名は例外 行継続の \括弧の方が望ましいが、 with文やassert等では使ってよいwith文中を除いて使うなdocstringの使用 non-publicメソッドでは不要、他は書け non-publicで短くて明らかなメソッドを除いて書け docstringのスタイル なし(PEP257に書くべき内容が記述) あり コメントの内容 自明なことは書くな コード自体の説明をするな、英語の文法・綴り・句読法を守れ 文字列の引用符 '"どちらでもよい プロジェクト内で原則どちらを使うか決めること 複数行文字列(docstring除く) 三重引用符を使うときは """文字列に原則 'を使うことにしたプロジェクトでは'''でも良い。また他の書き方への言及ありTODOコメントのスタイル なし あり importの順序 標準ライブラリ→外部ライブラリ→ローカルライブラリ ほぼPEP8と同じだが、辞書順であることが明記 1文字変数 l,O,I禁止原則禁止。例外はカウンタ・イテレータの i等、exceptでのe、ファイルオブジェクトのf前後に _を付ける命名_xxx,__xxx,xxx_を使うケースに言及非publicなら _xxx、__xxxは非推奨一貫性 拘り過ぎる奴は心が狭い 一貫しろ 括弧で行を結合するときの書き方
# PEP8でもGoogleでもOK foo = long_function_name(var_one, var_two, var_three, var_four) meal = (spam, beans) foo = long_function_name( var_one, var_two, var_three, var_four) meal = ( spam, beans) # PEP8では許容、GoogleではNG(スペースが2個になっている) foo = long_function_name( var_one, var_two, var_three, var_four) # PEP8では言及なし、GoogleではOK foo = { long_dictionary_key: value1 + value2, ... } foo = { long_dictionary_key: long_dictionary_value, ... } # PEP8では言及無し、GoogleではNG foo = { long_dictionary_key: long_dictionary_value, ... } # PEP8ではOK、Googleでは言及無し? def long_function_name( var_one, var_two, var_three, var_four): print(var_one) # PEP8ではOK、Googleでは言及無し、もしかしたらNG my_list = [ 1, 2, 3, 4, 5, 6, ] result = some_function_that_takes_arguments( 'a', 'b', 'c', 'd', 'e', 'f', ) # Googleはこの書き方を好んでいる気がする my_list = [ 1, 2, 3, 4, 5, 6, ] result = some_function_that_takes_arguments( 'a', 'b', 'c', 'd', 'e', 'f')
- PEP8では2項演算子の前で改行、Googleでは言及無し
- PEP8ではif文の条件が長くなった時の記述を例示、Googleでは言及無し
- Googleでは関数アノテーションを使ったときの記法を規定、PEP8では言及無し
その他、Google Style Guideのみ言及がある事柄
class定義文と最初のメソッドの間は1行空けろif __name__ == '__main__'を使いましょう- 関数が40行を超えたら分割を検討しましょう
- 2つの文字列の連結は
+を使う。それ以上に連結するときは%,str.format(),f-string,str.join()を使う。map()とfilter()を組み合わせるな- ラムダ式はワンライナーのためなら使ってよいが、ラムダ式部分が60-80文字超になるときはnested関数を使おう
operatorモジュールにある関数をラムダ式で書くな- ファイル、ソケットは
with文を使おう- シェバンは書かなくてよい、直接実行しないファイルに書くのは無意味
- 無駄な
()は書くな。タプルを明示する()は書こう。- 内包表記・ジェネレータ式で
for文を2個以上、または制御文を2個以上使うな@staticmethodは原則使わずに、モジュールレベル関数にしよう@classmethodは名前付きコンストラクタとして使うメソッドか、クラスのグローバル状態を変更するメソッドに使おう- デフォルト引数の定義でミュータブルを使うな
- グローバル変数は避けて、定数を使おう
- type annotationの書き方
感想
Googleよ、PEP 8と同じところは同じって書いてくれよ全部読むの大変だったorz。docstringやtype annotationの書き方を結構詳しく決めているところは良かった。
- 投稿日:2020-08-23T17:16:17+09:00
Pythonの環境構築をしないでプログラムを実行させる!!(Google Colaboratoryの始め方)
始めに
僕は1年ぐらい前に人工知能についてよく分からないなら説明を聞くより作った方が早いだろと考えUdemyでPythonを使った人工知能の作り方についての動画を購入しましたが、numpyが上手くインストール出来なくて挫折してしまいました(笑)。でも今回の環境ではnumpyを使う事が出来ました!同じ悩みで困っていたらぜひ参考にして下さい。そうでなくても、pythonは何をして環境構築をしたら良いのか分からないと言う人や、タブレットでプログラミングをした人に、この記事を読んでくれると嬉しいです。
google driveを使って
今の時代で知らない人は居ないと思いますが、googleではアカウントを作ると無料で15Gの容量をクラウド上に保存できる様になります。今回はそのgoogle driveの拡張機能?を使ってpythonで実行させて見ましょう。※今回はgoogleアカウントの作り方の作り方については解説しません、ゴメンなさい。YouTubeで分かりやすい解説動画がありましたのでこちらからどうぞ!
google Colaboratoryの下準備
まず始めにgoogleのアカウントにログインしてからドライブを開いて見て下さい。開くと下の画像のようになるはずです。
そうしたら、新規→その他→アプリを追加を押して下さい。そうすると下のようなウィンドウが表示されます。
appの検索から"Colaboratory"と検索して下さい。そうした左下に青色のアプリを追加するボタンを押して下さい。それでもう一度driveを読み込み直したら新規→その他→Colaboratoryが開けるようになっています。
これで準備は完了です。とても簡単ですね!google Colaboratoryを使って見よう!
Colaboratoryを開くと初めはこんな感じのウィンドウになっています。
それではpythonが実際に使えるかやって見ましょう。
しっかりとpythonが使える事がわかりました。
※ちなみにプログラムの実行はenter+shiftを同時に押せば解決です。最後にnumpyが動かせるか試して見ます。numpyの基本的な機能のrangeが使えるか試して見ます。
import numpy as np number = np.array(range(1,10)) print(number)※これがコードです
成功しましたね。これでnumpyも使える事がわかったので人工知能についての学習をもう一度やり直して見たいと思います。(なんだかジュピタノート見たいですね!)最後に
今回はタマタマYouTubeを見ていたら見つけたのでそのリンクを載せておきます。なかなか面白いので見て見て下さい。
順番は逆になってしまいましたが、最後まで記事を見てくてありがとうございました。まだまだプログラム経験は浅いのでも違っていたら押してくれると嬉しいです。
- 投稿日:2020-08-23T16:41:35+09:00
Pythonでスクレイピング
BeautifulSoupの準備はこちら
最近モチベーション上がらなくて、上げるためにとりあえず書くことにしました。
本当に基礎の基礎なので悪しからずとりあえず、BeautifulSoupを実行してみます。
from urllib.request import urlopen from bs4 import BeautifulSoup # 取得するページ html = urlopen('http://www.pythonscraping.com/pages/page1.html') bs = BeautifulSoup(html.read(), 'html.parser') # h1タグを返す print(bs.h1)2行目の
from bs4 import BeautifulSoup
部分でBeautifulSoupをインポートする。
実行結果は下記となる。
http://www.pythonscraping.com/pages/page1.html
上記ページのh1タグだけ取得できることがわかる。次回はちゃんとした内容で投稿します。
参考文献
PythonによるWebスクレイピング(オライリー・ジャパン)
- 投稿日:2020-08-23T16:12:29+09:00
データプリパレーションツールPaxataを触ってみた
私は受託で顧客企業のデータ分析をしています。
先日、顧客からPaxataの導入検討のため、製品の評価をしてほしいという依頼を受け、Paxataを試験的に触る機会をいただきました。
Paxataは2019年にDataRobotが買収1したデータプリパレーションツールです。
利用するにはサブスクか、Azure/AWSのVMに入れてもらかの2パターンがあり、今回は後者でした。
調べても日本語の情報があまり出てこないので、自分で触ってみた感想を投稿することにしました。どなたかの参考になれば幸いです。感想
あくまで感想です。それぞれがメリットになるかデメリットになるかは、時と場合によると思います。
- ノンコーディングといえど、ある程度のプログラミング的思考力は必要
- ノンコーディングツールは魔法じゃない
- 開発者自身がパーツの組み合わせを設計してデータ加工する必要があるので、全くプログラミングできない人が使うにはハードルが高い
- 視認性が高く、どんな処理をやってるか把握しやすい
- 詳細設計書とか書いてる場合は不要になりそう
- 処理結果のプレビュー機能や文字列の自動名寄せ機能がある
- 置換処理とかで置換前と置換後をプレビューで比較できる
- 文字列の
株式会社と(株)くらいの違いなら自動で名寄せしてくれる- あまり複雑な処理はできない
- 処理は直列でネストも分岐も繰り返しもできない
- 誰が作っても同じような水準の仕上がりになる(
SIerが好きそう)- 作った処理をPythonにエクスポートするとかできない
- ベンダーロックインされる
- 現状、機械学習との連携はDataRobotのみサポート
- 加工したデータをscikit-learnとかで使うには、一旦DBやファイルにエクスポートする必要がある
- レビューやデプロイのプロセスを組み込みにくい
- 開発/本番環境といったデプロイの概念がないので、メンテナンス時には運用中のプロダクトを直接触ることになる
- gitのようにプルリクを出すことも差分を見ることもできないので、レビューしにくい
- pytestやJUnitのようなテスト機能はない
- バージョン管理機能があるので、前のバージョンに戻すとかはできる
実際の操作
Paxataは次の3つのコンポーネントで構成されています。
# コンポーネント 説明 1 ライブラリ データセットを管理(プロジェクトの出力もここで管理) 2 プロジェクト データ加工処理の定義 3 プロジェクトフロー プロジェクトの処理フローと実行スケジュールの定義 開発するときは、
- ライブラリにデータセットをインポート
- プロジェクトで処理を定義
- プロジェクトフローで処理をスケジューリング
- 処理結果をライブラリで確認
というのが大まかな流れになります。
ライブラリにデータセットをインポート
試しにCSVファイルをインポートすると、こんな感じになります。データはこちらからお借りしました。
「プロファイル」という機能を使うと、カラムごとの基本統計量やカテゴリに関する情報を出してくれます。
プロジェクトで処理を定義
カラムのデータ型を変えたり置換したりしようとすると、こんな感じで処理結果のプレビューが出ます。
「計算」というツールで、Excelみたいな関数を使って新しいカラムを作ることもできます。
「集計」というツールで、集計もできます。ただし、これは新しいカラムとして追加するタイプの集計で、例えばCount Encodingするときに使うようなものです。
普通の(?)集計をする場合は「シェイプ」というツールを使います。
プロジェクトフローで処理をスケジューリング
作ったプロジェクトをスケジューリングしてみます。時間間隔以外にcrontabフォーマットの指定もできます。
グラフ表示するとこんな感じです。プロジェクトが1つしかないとしょぼいですが…。
終わり
この記事は顧客企業およびPaxataの販売代理店に許諾を得て執筆しています。
- 投稿日:2020-08-23T14:51:15+09:00
【PyTorch】違うバージョン間での型の違う演算には気を付けようメモ
TL;DR
torch=<1.2.0 と torch=>1.4.0において、float型とtorch.int64型の演算(torch.sub)結果が違った。
torch=<1.2.0では、(float型) と (torch.int64型)の演算 = (torch.int64) となる。
torch=>1.4.0では、(float型) と (torch.int64型)の演算 = (torch.float32) となる。torch=<1.2.0では、演算結果に対して(float型)の小数点以下の情報が消えてしまう。
実行する環境は統一させる、または演算の際はキャストを考慮する事が大事である。はじめに
Qiitaに初投稿させていただきます。A (twitter)です。
普段はPyTorchを使用して、楽しくNNを構築してお勉強をしております。
そんな中で、異なるPyTorchのバージョン間での数値演算を行った際にこちらの問題にぶち当たったので、メモとして記しておきます。もし間違いがあればコメント等で指摘していただけると幸いです。
※「そもそも違う型同士で演算するな!」という意見ございましたら、誠におっしゃる通りでございます。大変申し訳ございません。
背景
そもそも、なぜ私がPyTorchの違うバージョン間を行き来してるのかと言いますと、
コロナの影響で研究室に立ち入る頻度が減ったため、家のゲーミングPCで環境構築すれば研究が色々楽になるのではと思って以下のように環境を構築しました。
研究室環境
- Python3.5 + CUDA9.0 + torch==1.1.0
家環境
- Python3.7 + CUDA9.2 + torch==1.5.0
そして、研究室で走らせていたコードを、家で走らせたら普通に動いたので「ええやんええやん」と思って悠々自適に研究ライフをエンジョイしていました。
※「環境くらい再現性保つために全部統一しろよ!」という意見ございましたら、誠におっしゃる通りでございます。大変申し訳ございません。(n回目)
問題
それからは、家でコーディング作業と実行出来るかどうかの確認をし、研究室でNNの学習と検証をしていたところ、2つの環境間で異なる結果が出力されているのが目に留まりました。
以下に問題の再現として、Pythonのコマンドラインを示します。
研究室環境
- Python3.5
- CUDA9.0
- torch == 1.1.0
>>> import torch >>> torch.__version__ '1.1.0' >>> float = 3.14 >>> tensor_int = torch.tensor(3, dtype=torch.int64) >>> >>> type(float) <class 'float'> >>> tensor_int.dtype torch.int64 >>> >>> ans = torch.sub(float, tensor_int) >>> ans tensor(0) >>> >>> ans.dtype torch.int64 >>>家環境
- Python3.7
- CUDA9.2
- torch==1.5.0
>>> import torch >>> torch.__version__ '1.5.0' >>> float = 3.14 >>> tensor_int = torch.tensor(3, dtype=torch.int64) >>> >>> type(float) <class 'float'> >>> tensor_int.dtype torch.int64 >>> >>> ans = torch.sub(float, tensor_int) >>> ans tensor(0.1400) >>> >>> ans.dtype torch.float32 >>>見てわかる通り、演算結果"ans"のデータの型が研究室環境では
torch.int64、家環境ではtorch.float32となっています。つまり、torch == 1.1.0では"float"の小数点以下の情報が"ans"では消えてしまっていたのです。こちらの問題はおそらくtorchのバージョン間の問題に依存していると思われます。
(torch==1.5.0ではtorch.int64になってしまう問題が解決されていると捉えてます。ありがとう PyTorch。)検証
では、torchのバージョン間の問題に依存していると予想したことから、
torch==1.1.0 ~ 1.5.0のどこでこの仕様が変わったのか、検証してみました。検証した環境は以下の通りです。
- Python 3.7.7
- torchは全てにおいてcpu版を使用
検証したバージョンは以下の通りです。
- torch==1.1.0
- torch==1.2.0
- torch==1.4.0
- torch==1.5.0
(1.3.0はPyTorchアーカイブになかったので、検証してません。)
torch==1.1.0 (再掲)
>>> import torch >>> torch.__version__ '1.1.0' >>> float = 3.14 >>> tensor_int = torch.tensor(3, dtype=torch.int64) >>> >>> ans = torch.sub(float, tensor_int) >>> ans tensor(0) >>> >>> ans.dtype torch.int64 >>>torch==1.2.0
>>> import torch >>> torch.__version__ '1.2.0' >>> float = 3.14 >>> tensor_int = torch.tensor(3, dtype=torch.int64) >>> >>> ans = torch.sub(float, tensor_int) >>> ans tensor(0) >>> >>> ans.dtype torch.int64 >>>torch==1.4.0
>>> import torch >>> torch.__version__ '1.4.0' >>> float = 3.14 >>> tensor_int = torch.tensor(3, dtype=torch.int64) >>> >>> ans = torch.sub(float, tensor_int) >>> ans tensor(0.1400) >>> >>> ans.dtype torch.float32 >>>torch==1.5.0 (再掲)
>>> import torch >>> torch.__version__ '1.5.0' >>> float = 3.14 >>> tensor_int = torch.tensor(3, dtype=torch.int64) >>> >>> ans = torch.sub(float, tensor_int) >>> ans tensor(0.1400) >>> >>> ans.dtype torch.float32 >>>結果からtorch==1.4.0から仕様が変わったようですね。やはりtorchのバージョンに依存していました。
おそらく 公式ドキュメント や pytorch 1.4 リリース情報 を読めばわかることだと思います。
(私は見つけられませんでした。。。)おわりに
「違うバージョン間での型の違う演算」という題目のもと、torchの異なるバージョン間でのfloat型とtorch.int64型の演算に注目して、出力結果の違いを検証しました。
私から言えることは、
- 実験を行う際は開発環境には注意しましょう
- 演算を行う際はキャストには注意しましょう
- そして、PyTorchの開発陣の方々本当にありがとう
です。
私自身、研究室環境でCUDA9.0を入れていたため、torch==1.1.0を使用していたという妥協のもと、このような結果を招いてしまいました。これを機に、研究室環境を家環境に揃えるためPython,CUDA,torchをアップグレードしました。
みなさんも今一度、開発環境について見つめ直してみてはいかがでしょうか!
- 投稿日:2020-08-23T14:39:38+09:00
PythonでABC176 Dを解く
はじめに
昨日のABCで解けなかったE - Bomberをやります。
E - Bomber
gridを二次元配列で保持すると管理が面倒なのと時間が厳しいので、$H,W$それぞれの軸で爆弾の数を管理します。
$H,W$軸でそれぞれの爆弾の数の最大値を選んで、それぞれの最大値の和を返せば正解になりそうですが、それだけだと不十分です。これだと、交差している点に爆弾がある場合に対応できていないからです。交差している点に爆弾があるときは、それぞれの最大値の和-1になります。交差している点はdictにtupleを入れて保持します。0は爆弾が無い点、1は爆弾がある点です。
from collections import defaultdict h, w, m = map(int, input().split()) cnt_h = [0] * h cnt_w = [0] * w dic = defaultdict(int) for _ in range(m): h_m, w_m = map(int, input().split()) cnt_h[h_m - 1] += 1 cnt_w[w_m - 1] += 1 dic[(h_m - 1, w_m - 1)] += 1 max_h = max(cnt_h) max_w = max(cnt_w) mh = [] mw = [] for i in range(h): if max_h == cnt_h[i]: mh.append(i) for i in range(w): if max_w == cnt_w[i]: mw.append(i) flag = False for i in mh: for j in mw: if dic[(i, j)] == 0: flag = True #0の点があるならそれが最大値になるのでbreakします。 break if flag: break if flag: print(max_h + max_w) else: print(max_h + max_w - 1)
- 投稿日:2020-08-23T14:39:38+09:00
PythonでABC176 Eを解く
はじめに
昨日のABCで解けなかったE - Bomberをやります。
E - Bomber
gridを二次元配列で保持すると管理が面倒なのと時間が厳しいので、$H,W$それぞれの軸で爆弾の数を管理します。
$H,W$軸でそれぞれの爆弾の数の最大値を選んで、それぞれの最大値の和を返せば正解になりそうですが、それだけだと不十分です。これだと、交差している点に爆弾がある場合に対応できていないからです。交差している点に爆弾があるときは、それぞれの最大値の和-1になります。交差している点はdictにtupleを入れて保持します。0は爆弾が無い点、1は爆弾がある点です。
from collections import defaultdict h, w, m = map(int, input().split()) cnt_h = [0] * h cnt_w = [0] * w dic = defaultdict(int) for _ in range(m): h_m, w_m = map(int, input().split()) cnt_h[h_m - 1] += 1 cnt_w[w_m - 1] += 1 dic[(h_m - 1, w_m - 1)] += 1 max_h = max(cnt_h) max_w = max(cnt_w) mh = [] mw = [] for i in range(h): if max_h == cnt_h[i]: mh.append(i) for i in range(w): if max_w == cnt_w[i]: mw.append(i) flag = False for i in mh: for j in mw: if dic[(i, j)] == 0: flag = True #0の点があるならそれが最大値になるのでbreakします。 break if flag: break if flag: print(max_h + max_w) else: print(max_h + max_w - 1)
- 投稿日:2020-08-23T14:36:59+09:00
バブルソート、選択ソート、挿入ソート、シェルソート、マージソート、クイックソート、計数ソート
Python でソートアルゴリズムをまとめておきます。
バブルソート(Bubble Sort)
平均計算量: $O(n^2)$
最悪計算量: $O(n^2)$bubble.pyfor i in range(N-1, 0, -1): for j in range(i): if a[j] > a[j+1]: a[j], a[j+1] = a[j+1], a[j]verify: http://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=4783238
選択ソート(Selection Sort)
平均計算量: $O(n^2)$
最悪計算量: $O(n^2)$selection.pyfor i in range(N): minj = i for j in range(i, N): if a[j] < a[minj]: minj = j a[i], a[minj] = a[minj], a[i]verify: http://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=4783283
挿入ソート(Insertion Sort)
平均計算量: $O(n^2)$
最悪計算量: $O(n^2)$insertion.pyfor i in range(1, N): v = a[i] j = i - 1 while j >= 0 and a[j] > v: a[j+1] = a[j] j -= 1 a[j+1] = vverify: http://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=4783260
シェルソート(Shell Sort)
内部で用いる挿入ソートの間隔列として、ウィキペディアの記事にあるように、$h = \frac{3^i - 1}{2}$ を満たす整数を大きい方から採用しました。
平均計算量: 間隔列として上記を採用した場合、$O(n^{1.25})$ と予想されている
最悪計算量: 間隔列として上記を採用した場合、$O(n^{1.5})$shell.pydef insertion_sort(h): for i in range(h, N): v = a[i] j = i - h while j >= 0 and a[j] > v: a[j+h] = a[j] j -= h a[j+h] = v hs = [] h = 1 while h < N+1: hs.append(h) h = 3 * h + 1 hs.reverse() for h in hs: insertion_sort(h)verify: http://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=4783355
マージソート(Merge Sort)
平均計算量: $O(n \log n)$
最悪計算量: $O(n \log n)$merge.pyINF = 1e10 # 配列要素の取りうる最大値よりも大きく def merge(left, mid, right): l = a[left:mid] r = a[mid:right] l.append(INF) r.append(INF) i = 0 j = 0 for k in range(left, right): if l[i] <= r[j]: a[k] = l[i] i += 1 else: a[k] = r[j] j += 1 def merge_sort(left, right): if right - left >= 2: mid = (left + right) // 2 merge_sort(left, mid) merge_sort(mid, right) merge(left, mid, right) merge_sort(0, N)verify: http://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=4783399
クイックソート(Quick Sort)
平均計算量: $O(n \log n)$
最悪計算量: $O(n^2)$quick.pydef partition(left, right): x = a[right] i = left-1 for j in range(left, right): if a[j] <= x: i += 1 a[i], a[j] = a[j], a[i] a[i+1], a[right] = a[right], a[i+1] return i+1 def quick_sort(left, right): if right - left >= 2: pivot = partition(left, right-1) quick_sort(left, pivot) quick_sort(pivot, right) quick_sort(0, N)verify: http://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=4783489
計数ソート(Counting Sort)
バケットソート(Bucket Sort), ビンソート(Bin Sort) の一種でもある
平均計算量: $O(n + k)$
最悪計算量: $O(n + k)$counting.pyK = 100000 # 配列要素の取りうる種類数よりも大きく b = [0 for i in range(len(a))] c = [0 for i in range(K)] for v in a: c[v] += 1 for i in range(K-1): c[i+1] += c[i] for j in reversed(range(N)): b[c[a[j]]-1] = a[j] c[a[j]] -= 1 # b がソート済み配列verify: http://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=4783628
- 投稿日:2020-08-23T14:36:59+09:00
バブルソート、選択ソート、挿入ソート、シェルソート、マージソート、クイックソート、計数ソート(Python)
Python でソートアルゴリズムをまとめておきます。
バブルソート(Bubble Sort)
平均計算量: $O(n^2)$
最悪計算量: $O(n^2)$bubble.pyfor i in range(N-1, 0, -1): for j in range(i): if a[j] > a[j+1]: a[j], a[j+1] = a[j+1], a[j]verify: http://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=4783238
選択ソート(Selection Sort)
平均計算量: $O(n^2)$
最悪計算量: $O(n^2)$selection.pyfor i in range(N): minj = i for j in range(i, N): if a[j] < a[minj]: minj = j a[i], a[minj] = a[minj], a[i]verify: http://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=4783283
挿入ソート(Insertion Sort)
平均計算量: $O(n^2)$
最悪計算量: $O(n^2)$insertion.pyfor i in range(1, N): v = a[i] j = i - 1 while j >= 0 and a[j] > v: a[j+1] = a[j] j -= 1 a[j+1] = vverify: http://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=4783260
シェルソート(Shell Sort)
内部で用いる挿入ソートの間隔列として、ウィキペディアの記事にあるように、$h = \frac{3^i - 1}{2}$ を満たす整数を大きい方から採用しました。
平均計算量: 間隔列として上記を採用した場合、$O(n^{1.25})$ と予想されている
最悪計算量: 間隔列として上記を採用した場合、$O(n^{1.5})$shell.pydef insertion_sort(h): for i in range(h, N): v = a[i] j = i - h while j >= 0 and a[j] > v: a[j+h] = a[j] j -= h a[j+h] = v hs = [] h = 1 while h < N+1: hs.append(h) h = 3 * h + 1 hs.reverse() for h in hs: insertion_sort(h)verify: http://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=4783355
マージソート(Merge Sort)
平均計算量: $O(n \log n)$
最悪計算量: $O(n \log n)$merge.pyINF = 1e10 # 配列要素の取りうる最大値よりも大きく def merge(left, mid, right): l = a[left:mid] r = a[mid:right] l.append(INF) r.append(INF) i = 0 j = 0 for k in range(left, right): if l[i] <= r[j]: a[k] = l[i] i += 1 else: a[k] = r[j] j += 1 def merge_sort(left, right): if right - left >= 2: mid = (left + right) // 2 merge_sort(left, mid) merge_sort(mid, right) merge(left, mid, right) merge_sort(0, N)verify: http://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=4783399
クイックソート(Quick Sort)
平均計算量: $O(n \log n)$
最悪計算量: $O(n^2)$quick.pydef partition(left, right): x = a[right] i = left-1 for j in range(left, right): if a[j] <= x: i += 1 a[i], a[j] = a[j], a[i] a[i+1], a[right] = a[right], a[i+1] return i+1 def quick_sort(left, right): if right - left >= 2: pivot = partition(left, right-1) quick_sort(left, pivot) quick_sort(pivot, right) quick_sort(0, N)verify: http://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=4783489
計数ソート(Counting Sort)
バケットソート(Bucket Sort), ビンソート(Bin Sort) の一種でもある
平均計算量: $O(n + k)$
最悪計算量: $O(n + k)$counting.pyK = 100000 # 配列要素の取りうる種類数よりも大きく b = [0 for i in range(len(a))] c = [0 for i in range(K)] for v in a: c[v] += 1 for i in range(K-1): c[i+1] += c[i] for j in reversed(range(N)): b[c[a[j]]-1] = a[j] c[a[j]] -= 1 # b がソート済み配列verify: http://judge.u-aizu.ac.jp/onlinejudge/review.jsp?rid=4783628
- 投稿日:2020-08-23T14:26:11+09:00
AtCoder ABC176
総括
C問題までACできた。
目標がA-C問題のACなので目標達成。A - Takoyaki
問題に沿って書いた。
import math N,X,T = map(float,input().split()) a = math.ceil(N / X) print(int(a * T))B - Multiple of 9
これも問題に沿って書いた。
N = list(map(int,input().split())) a = 0 for i in range(len(N)): a += N[i] if a % 9 == 0: print("Yes") else: print("No")これでよかったみたい。簡潔で分かりやすい。
N = int(input()) if N % 9 == 0: print('Yes') else: print('No')C - Step
前の人と同じ高さになるまで台を足していく。
N = int(input()) A = list(map(int,input().split())) ans = 0 for i in range(1,N): diff = A[i - 1] - A[i] if diff <= 0: pass else: ans += diff A[i] += diff print(ans)D - Wizard in Maze
D問題以降は未知の領域だった。
過去問やアルゴリズムの勉強を頑張ろう。最後に
目標のC問題までACできたのでよかった。
早く正確にを目標に頑張りたいところ。
- 投稿日:2020-08-23T14:19:36+09:00
numpy arrayの要素を真偽判定したい
やりたいこと
aとbという二つのnumpy arrayがある.
bの要素がaに含まれているか知りたい...とりあえずこれでできるみたい
example.pyimport numpy as np a = np.array([[1,2,3],[2,3,4],[4,5,6]]) b = np.array([4,5,6]) (a==b).all(axis=1).any()結果↓
True使っている関数
all関数
全ての要素が真であるときにTrueを返す関数
【引数】
・axis
0を指定すると行方向の結果を, 1を指定すると列方向の結果を返すany関数
いずれかの要素が真であるときにTrueを返す関数
- 投稿日:2020-08-23T14:16:43+09:00
Pythonでファイルに書き込みをしたい
Pythonプログラムでの出力結果をファイルに書き込みたい...
例
example.pyfile_path = "./test.txt" food = "orange" text="My favorite food is "+ food with open(file_path, mode='w') as f: f.write(text)$ cat ./text.txt My favorite food is orange使った文法・関数・メソッド
with文
コードの開始処理と終了処理を実行できるようにする
open()
ファイルを開くために使用した関数
【引数】
開きたいファイルのパスwrite()
文字列をファイルに書き込む役割を有するメソッド
- 投稿日:2020-08-23T14:11:28+09:00
【AtCoder】普通の人である私が緑になるまでにしたこと
こんにちは、Kotaです。
ご閲覧いただきありがとうございます!昨日開催されましたAtCoder Beginner Contest 176でレーティングが緑になりました!
ついに!入緑しました!!!
— Kota (@kota0501_orca) August 22, 2020
ここまで長かったのでめちゃくちゃ嬉しい?
kota0501さんのAtCoder Beginner Contest 176での成績:1754位
パフォーマンス:1241相当
レーティング:754→815 (+61) :)
Highestを更新し、6 級になりました!#AtCoder #ABC176 https://t.co/ONTPDcUzzV pic.twitter.com/jQKX7gwBsa要約
- 競プロ開始してから7ヶ月弱で緑になったよ!
- この界隈は人外な人が多いよ!(人外についての説明は記事内で!)
- だから普通の人である私が緑になるまでにしたこと&していないことをまとめるよ!
1. はじめに
競技プログラミング(競プロ)は、2020年1月12日に初コンテストに出場し、そこから取り組んでいきました。
そして、始めてから昨日(2020年8月22日)のコンテストまでの7ヶ月弱で、レーティングが緑(800-1199)になりました。
この章で、レート感についてと、期間についてを所感として書いておきます。レート感
緑レートのレベル感については、chokudaiさん(AtCoder社 社長)が以下のようにまとめてくれています。(2020年8月23日時点)
緑色 (Cランク R800~1199 上位30%)
緑色になれれば、「競技プログラミングに熱心に取り組んでいる人」と考えて問題ないでしょう。要求レベルも決して低くなく、出場回数が足りないとマイナス補正がかかるため、運だけで到達することはまず出来ないラインです。他社アルゴリズム力判定サービスだと、上位1%の最高ランクが付く実力です。(あくまで「アルゴリズム力部分だけであることに注意してください)印象としては、
- 学生ならかなり優秀。
- エンジニアとしてもある程度の安心感がある。論理的に複雑な処理の実装に対応できない、なんてことはなさそう、くらいには思える。データ量が多い現場など、計算量の多い処理が要求される現場でなければ、このレート帯以上を求める必要はほぼない。
くらいの印象です。もちろんアルゴリズム力しか計ってないので個人差があります。
技術的な部分では、
- if、forはもちろん、それを組み合わせて2次元配列に対して操作をしたり、深さ優先探索や幅優先探索などのキューや再帰を使った実装も出来る。
- 簡単な動的計画法の問題や、数学的に工夫する問題など、計算量の工夫も出来始める。
という感じです。
このレベル感については、賛否両論あるようですが、今回は関係がないので割愛します。
このレベル感を見て、どう思うかは人によると思いますが、普通の人である私は、
「少しプログラミングはやったことあるし、競プロ自体に慣れればすぐに到達できそう!
if, for, 2次元配列って書いてあるし、そのくらいなら分かる!」と思いました。(都合が良い部分だけを読み取った結果です。)
結論を言うと、この認識はかなり間違っていたと今は痛感しています。
上の認識だと、レート200-300(灰色)が良いところだと思います。期間
競プロを開始してから緑になるまでの期間の7ヶ月弱についてですが、この界隈では決して早くはありません。
chokudaiさんが以下のように言及しているので「人外」というワードを使いますが、成長速度が異常な「人外」がとても多いです。
【競プロの各色に対する認識オススメ】
— chokudai(高橋 直大)??? (@chokudai) June 29, 2020
・2色上は人外だと思うのが大切!比較しちゃだめ!1色上に追いついたところで人間に戻してあげよう!
・1色上は強い人!目標にするのは良いけど勝てなくて当たり前!いつかは追いつけたらいいなくらいに思おう!
・同色でも成長がヤバいやつはやっぱり人外!観測した範囲だけでこのような人外がいました。(人外度昇順)
- 1ヶ月で緑レート到達
- 半年で青レート到達
- 1回のコンテストで水レート到達
これらは人外度が高い人をピックアップしているのですが、これらとはインパクトが弱いものの十分に人外な人だらけです。
特にTwitterではこういった人が目立つため、「これが普通なのかー。」と最初は勘違いしてしまいます。
そして、どうしても比較していまい、「なんで自分は…。」と思うところまでがワンセットです。そのため、普通の人である私が、一般的(?)な期間で緑レートになるまでにしたことと、連呼している私(普通の人)のスペックを書いていきます。
記事の構成
記事の構成はこのようになってます。
少し長いですが読んでいただけると嬉しいです!2. 普通の人である私のスペック
前提として、普通の人というのは定量的に測れるものではありません。
しかし、
「普通の人?どうせよくいる強い人なのでは?」
と思われてしまうのも嫌なので簡単にですが、私のスペックを書きます。
- 新卒1年目のWebエンジニア(ここ2ヶ月間で書いたコードは0行)
- 地方国立大学学部卒
- 高専からの3年次編入なのでセンター数学経験なし
- 基本情報技術者試験を取得
- データ分析用途でPythonは使ったことがある(AtCoderではPython(PyPy )を使用している)
要するに競プロで大事である、高校数学のちゃんとした勉強経験がないということです。
これを見てどう感じ取るかも人それぞれですが、競プロ界隈では間違いなく上位ではないです。
逆にプログラミング自体は高専に通っていたこともあり、早めに始めたことから、総合的にみて特段に低いとも思っていないため、普通の人と言わせてもらっています。3. 緑になるまでにしたこと&していないこと
次に、そんな普通の人である私が緑レートになるまでにしたことを書いていきます。
また、していないことを書かれた記事がほぼなかったのでそちらも書きたいと思います。3.1. 緑になるまでにしたこと
したことは次のようなことです。
- 毎日AC
- 高校数学の勉強
次からはこれらのしたことの詳細を書いていきます。
毎日AC
AtCoder ProblemsでStreakが見れるので毎日ACすることを日課にしてます。
簡単な問題を埋める、いわゆる虚無埋めをやってしまいがちなのですが、それでも解かない日があるよりかはましと思って解いてます。(習慣化することが大事!)
Current Streakは、Unique ACがカウント対象と知らずに途中で切れました。
違う解法で解き直したら見事に切れてしまいました。笑
みなさんも気をつけてください!ここから記念にぺたぺた貼っていきます。
Achievement
Difficulty Pies
Climbing -Colored-
Heatmap -Max Difficulty-
あと、GitHubに競プロでUnique ACしたものを毎日定時に自動PUSHするようにしています。
精進によって草が生えていくため、モチベーションにもなるのでおすすめです!高校数学の勉強
高校数学の美しい物語のサイトで勉強しました。
私的には難しいものが多いので飛ばし飛ばしで読んでいますが、様々な発見もあり面白いのでおすすめです。
これからも少しずつ読み進めていきたいと思います。
競プロは継続、つまりモチベーション維持が大切です。
そのため、モチベーション維持のためにTwitterアカウントを作成するというのがよくなされています。疑心暗鬼な気持ちで始めてみましたが大成功でした!
本界隈は、人外が多いのも事実なのですが、優しい人(⊇人外)がとても多いです。
様々なところで分からないところを教えあったり、励ましあったりしています。人によるとは思いますが、一人で黙々と精進するよりかは誰かと一緒に精進した方が精神的にも良いためおすすめです!
↑よければ、私のTwitterアカウントもフォローお願いします!一緒に精進していきましょう!
3.2. 緑になるまでにしていないこと
していないことは次のようなことです。
- 蟻本などの競プロ本購入
- バチャコン参加
- 外部コンテスト参加
次からはこれらのしていないことの詳細を書いていきます。
蟻本などの競プロ本購入
他にもchokudaiさんが著者のチーター本と呼ばれる競プロ本もあります。
アルゴリズムについての情報はネット上に有志の方がきれいにまとめてくださっているので購入していないです。
有志の方がまとめてくださっているよく勉強で使用させていただいたサイトについては、記事の最後でまとめています。
あと、私がPython(PyPy)を使用しているという理由もあります。(蟻本は参考実装がC++らしいので)バチャコン参加
AtCoder Problemsでよくバチャコンと呼ばれるバーチャルコンテストが開催されています。
くじかつと呼ばれるものはほぼ毎日開催されているようです。
レーティングに反映されないこともあり、まとまった時間をとることが厳しいため参加していないです。
外部コンテスト参加
このCodeforcesという海外コンテストに参加されている方が多いです。
参加してみたいとは思っているのですが、海外のコンテストなので時間が不規則かつ健康的な時間に開催していないことが多いので避けてしまっています。
ただコンテストへの参加は、モチベーションを保つ上で大事なことだと感じているので、可能であれば積極的に参加した方が良いと思います。
4. 学んだアルゴリズムとデータ構造
学んだアルゴリズムとデータ構造について書いていきます。
また、学んだはいいものの緑になる上でコンテストでは使わなかったものは明記したいと思います。
そして、その上で緑になる上での重要度を独断と偏見で書きます!
名前 使った(○)・使っていない(×) 重要度(高・中・低) bit全探索 ○ 高 二分探索 ○ 高 累積和 ○ 高 約数全列挙 ○ 高 素因数分解 ○ 高 GCD・LCM ○ 高 貪欲法 ○ 中 幅優先探索(BFS) × 中 深さ優先探索(DFS) × 中 imos法 × 低 動的計画法(DP) × 低 優先度付きキュー × 低 グラフアルゴリズム × 低 ダブリング × 低 Union-Find Tree × 低 こう見ると必要なのは、典型的なアルゴリズムスキルより、素早く正確な考察力だと分かります。
もちろん様々なアルゴリズムを使いこなせた方が良いのは間違いないと思いますが、緑になるだけならそこまで多くのアルゴリズムを学ばなくても良さそうです。5. 持ってるライブラリ
ライブラリというまでのものではありませんが、保存しているものを貼っておきます。
よく使うものは、すぐにコピペできるところに置いておくのが良いと思ってます!複数の数の最大公約数・最小公倍数
# 最大公約数 def gcd_list(numbers): return reduce(gcd, numbers) # 最小公倍数 def lcm_base(x, y): return (x * y) // gcd(x, y) def lcm_list(numbers): return reduce(lcm_base, numbers, 1)約数列挙
def make_divisors(n: int) -> list: divisors = [] for i in range(1, int(n**0.5)+1): if n % i == 0: divisors.append(i) if i != n // i: divisors.append(n//i) return divisors素因数分解
def prime_factorize(n: int) -> list: return_list = [] while n % 2 == 0: return_list.append(2) n //= 2 f = 3 while f * f <= n: if n % f == 0: return_list.append(f) n //= f else: f += 2 if n != 1: return_list.append(n) return return_listMOD用組み合わせ
def mod_cmb(n: int, k: int, p: int) -> int: if n < 0 or k < 0 or n < k: return 0 if n == 0 or k == 0: return 1 if (k > n - k): return mod_cmb(n, n - k, p) c = d = 1 for i in range(k): c *= (n - i) d *= (k - i) c %= p d %= p return c * pow(d, p - 2, p) % pUnion-Find木
class UnionFind(): # 作りたい要素数nで初期化 # 使用するインスタンス変数の初期化 def __init__(self, n): self.n = n # root[x]<0ならそのノードが根かつその値が木の要素数 # rootノードでその木の要素数を記録する self.root = [-1]*(n+1) # 木をくっつける時にアンバランスにならないように調整する self.rank = [0]*(n+1) # ノードxのrootノードを見つける def findRoot(self, x): if(self.root[x] < 0): # 根 return x else: # ここで代入しておくことで、後の繰り返しを避ける self.root[x] = self.findRoot(self.root[x]) return self.root[x] # 木の併合、入力は併合したい各ノード def unite(self, x, y): # 入力ノードのrootノードを見つける x = self.findRoot(x) y = self.findRoot(y) # すでに同じ木に属していた場合 if x == y: return # 違う木に属していた場合rankを見てくっつける方を決める if self.rank[x] > self.rank[y]: self.root[x] += self.root[y] self.root[y] = x else: self.root[y] += self.root[x] self.root[x] = y # rnkが同じ(深さに差がない場合)は1増やす if self.rank[x] == self.rank[y]: self.rank[y] += 1 # xとyが同じグループに属するか判断 def isSameGroup(self, x, y): return self.findRoot(x) == self.findRoot(y) # ノードxが属する木のサイズを返す def count(self, x): return -self.root[self.findRoot(x)]6. 使っているスニペット
あまりスニペットが共有されているところは見ないので、需要があるかは分かりませんが貼っておきます。
ABCではどうしても解く速度がとても重要になっている現状があるので、自身にあったスニペットは必須だと思っています。submit.pyimport sys, re from math import ceil, floor, sqrt, pi, factorial, gcd from copy import deepcopy from collections import Counter, deque from heapq import heapify, heappop, heappush from itertools import accumulate, product, combinations, combinations_with_replacement from bisect import bisect, bisect_left, bisect_right from functools import reduce from decimal import Decimal, getcontext # input = sys.stdin.readline def i_input(): return int(input()) def i_map(): return map(int, input().split()) def i_list(): return list(i_map()) def i_row(N): return [i_input() for _ in range(N)] def i_row_list(N): return [i_list() for _ in range(N)] def s_input(): return input() def s_map(): return input().split() def s_list(): return list(s_map()) def s_row(N): return [s_input for _ in range(N)] def s_row_str(N): return [s_list() for _ in range(N)] def s_row_list(N): return [list(s_input()) for _ in range(N)] def lcm(a, b): return a * b // gcd(a, b) sys.setrecursionlimit(10 ** 6) INF = float('inf') MOD = 10 ** 9 + 7 num_list = [] str_list = [] def main(): n = i_input() a, b = i_map() num_list = i_list() print() if __name__ == '__main__': main()7. おわりに
以上、普通の人である私が緑になるまでにしたことでした!
微力ですが同じく普通の人の力になれば嬉しいです!ここまで長い文章となりましたが、読んでいただきありがとうございました。
質問やアドバイス等ありましたらコメントしていただけると喜びます!次は水色を目指して精進していきます!
ありがとうございました!
8. よく勉強に利用させていただいたサイト
- 投稿日:2020-08-23T14:03:45+09:00
DeepRunning ~Level8~
Level8.深層学習 DAY4
8-1.Section1) TensorFlowの実装演習
●TensorFlowについて
•実務ではTensorFlowを活用することが多く、スクラッチで実装することは少ない。
•TensorFlow、Keras、Pytorchの順。
•TensorFlowはgoogleが作ったディープラーニングのフレームワークで、
調べる際もTensorFlowが多い。●実装「constant」
•TensorFlow ではテンソルというものを利用する。
•Session.run() で起動しないと中身も確認できない。●実装「placeholder」
・placeholderは、箱のようなものを用意している。
・placeholderは後から値を自在に変更できる。
・feed_dictで配列のx番目の要素を渡す。
⇒xをバッチに渡して実行するときなどに使用する。●実装「variables」
・a = tf.constant(10)と定義するとaに10を設定する。
・x = tf.Variable(1)後々に値を変えて更新できる。
⇒「calc_op = x * a」「update_x = tf.assign(x, calc_op)」
で値を更新している。
・init = tf.global_variables_initializer()は、
変数を初期化する。8-1-2 線形回帰の実装演習
●matplotlibのjitterの仕様(1度目にプロットできない)
matplotlibの下にinlineを書いてあげる。●コード
・iters_num ・・・何回学習するか。
・plot_interval ・・・10回ごとに結果を表示する。
・n = 100
x = np.random.rand(n)
d = 3 * x + 2 ・・・100個のランダムなxを用意し、3*x+2の値を作る。
・xは直線の値のため、noiseを加える。
⇒上下にまばらな値ができる。
・train = optimizer.minimize(loss) ・・・誤差を最小化する学習。
・loss = tf.reduce_mean(tf.square(y - dt)) ・・・回帰二乗誤差
・sess.run(train, feed_dict={xt:x_train,dt:d_train})
・・・trainを読み出し、feed_dictでx_train、d_trainを渡していく。
・W_val:[3.0194452]、b_val:[1.9318823]となっており、
d = 3 * x + 2のW:3とb:2に近い予測値になっている。●Tryの確認
・noiseの値を変更しよう
・dの数値を変更しようnoiseに0.55、bに9を設定する。
⇒W:[3.0428321]、b:[8.961408]と予測された。
その他変更して試したが、noiseが大きいと上手く回帰できない。☆考察☆
•noiseによるデータの作成で、直線上からどの程度ノイズを発生させるのか、
実際のデータがない時に一般データとの差を考えるのも難しいと感じた。
•Wとdがきちんと予測されると面白い。8-1-3 非線形回帰の実装演習
●非線形な一直線でない式を予測する。
●コード
・「d = -0.4 * x ** 3 + 1.6 * x ** 2 - 2.8 * x + 1」
非線形な解を作成している。
・Wが-0.4、1.6、-2.8、1と4つあるため、
WのVariableのoshapeを[4,1]と定義。
・optimizer = tf.train.AdamOptimizer(0.001)に変更している。
・[[-0.3990355]
[ 1.6032437]
[-2.8051274]
[ 1.0001277]] ・・・4つのWがきちんと予測できている。●Tryの確認
・noiseの値を変更しよう
・dの数値を変更しようnoiseを0.35にしてみた。
⇒[[-0.36423665]
[ 1.6244664 ]
[-2.8141403 ]
[ 0.96930456]] ・・・4つのWはほぼ予測ができている。
dを変更してみる。
「d = 0.4 * x ** 3 + 2.8 * x ** 2 - 2.8 * x + 10」
⇒[[ 0.31515315]
[ 3.8476086 ]
[-2.596497 ]
[ 7.5793443 ]] ・・・ちょっと厳しかったようだ。
☆考察☆
•noiseを大きくしても線形回帰と比べてあまり分散しなくなるようだ。
•dは線形回帰と比べても極端に予測がズレない。4つのWで複雑な非線形になると、
平均二乗誤差の収束は難しくなるが、線形回帰より大きく外れないと思った。●Tryの確認
次の式をモデルとして回帰を行おう
$?=30?^2+0.5?+0.2$誤差が収束するようiters_numやlearning_rateを調整しよう
☆考察☆
・iters_numを30000~35000回くらいに設定しないと収束しなかった。
データ作成数を増やすなど、様々な試行錯誤は必要だと感じた。
「optimizer = tf.train.AdamOptimizer(0.01)」を0.001⇒0.01にする差が大きい。
⇒iters_numは25000回くらいで十分だった。8-1-4 分類1層(mnist)
●MNISTの分類
手書き文字のデータセットで、28×28×白黒データで1チャンネル。
0~9のどの数字かを予測する。●Tryの確認
次の式をモデルとして回帰を行おう
・x:入力値, d:教師データ, W:重み, b:バイアス をそれぞれ定義しよう
・内容を確認する。
①x_batch[0]
②d_batch[0]
③x_batch[0].shape
④plt.imshow(x_batch[0].reshape(28,28))
☆考察☆
詳細はもう少し復習して深堀してみるが、
1層で出力のsoftmax関数が出力する0~9の分類が87%の精度はすごいなと感じた。8-1-5 分類3層(mnist)
●MNIST1層より精度を上げる。
・hidden_layerを2つ用意する。
・784(入力)⇒600、600⇒300⇒10(個の出力)のニューラルネットワーク
・隠れ層があるのでWやbを3つずつ用意。
・TensorFlowでは毎回Variableを定義する必要がある。
・Wが3つある場合:W1,W2,W3と、b1,b2,b3と定義する。
・出力の前にドロップアウトしており、汎化性能を上げるため、
あるニューロンを消している。
「drop = tf.nn.dropout(z2, keep_prob)」●Tryの確認
隠れ層のサイズを変更してみよう(600、300)
optimizerを変更しよう
☆考察☆
修正前の状態で90%となった。dropout_rate=0としたら91%となったが、
過学習になってしまってのかもしれない。
隠れ層のサイズを半分にしたところ、87%と精度が落ちた。
逆に800、500と増やすと91%と少し向上する。増やせばいいものだろうか。
⇒増やすと学習に時間がかかるようになった。
optimizerは、AdaGradを試してみた。
最終的な精度は90%だが、途中からの伸びが良かった。
講義と同じように全種類試した。
8-1-6 分類CNN(mnist)
●Conb×pool×Conb×poolで、
affin×dropout×affinという構造。
・1層目でreshapeにより28×28×1チャンネルの画像として処理。
・W_conb1は5×5×1×32というウェイト
5×5:CNNのフィルターサイズ
1×32:1チャンネルのものを32チャンネルに拡張する
・padding='SAME':shapeが変わらないようなpaddingを用意する。☆考察☆
ドロップアウト率が0.5の時は、93%の精度だった。
ドロップアウト率を0にしたら、精度が91%と落ちた。
ただ、90~96%をふらふらしており、学習モデルとしては安定していない印象。
x_batchでトレーニングデータを渡したもので、汎化性能は不明。
テストデータの場合、ドロップアウトさせた方が精度があがる。8-1-7 論文から実装する
●画像認識の最新モデルを実装するには?
・VGG
・AlexNet
・GoogLeNet
・Resnet
・Yolo⇒・VGG16でarxivと検索するとarxivのサイトにて論文を参照でき、
サイトから無料で手に入る。
・ABSTRACTを読む→ARCHITECTUREを見る。
RESULTで精度がどうなったか確認する。
・表とかテキストで実装した組み合わせなどがまとめられている。
・VGGはブログの記事になっているものもある。
・コードがGitHubに載っているので参考にする。
・AlexNet等でもアーカイブがあり、構成図を参照したりする。
「pytorch AlexNet」のように検索する。
・ResnetはDeep Residual Learning for Image Recognitionで、
他と同じようにアーカイブがある。
・最新のものでなければ、既にあるものから実装する。
・物体認識(Yolo)もPDFで提供されているが、
再現実装するのは大変だったりする。8-1-8 例題・例題解説
●例題3つ目
正解は(a)
●例題4つ目
正解はあ:(a)、い:(a)、う:(a)
☆確認テスト☆
・8-1-8-1 VGG・GoogLeNet・ResNetの特徴をそれぞれ簡潔に述べよ。【自分の回答】
VGG:16層と19層の構造のバージョンがある。勾配消失問題がある。
GoogLeNet:22層の構造。Inceptionモジュールが特徴。
ResNet:152層の構造。VGGの勾配消失問題を解決。【解答】
VGG:最も古くて2014年のモデル。Convolution、Convolution、max_poolという
単純なネットワークの積み重ねで出来ている。パラメータ数が多い。
GoogLeNet:Inception moduleを使ているのが特徴。1×1の畳み込みの次元削減。
ResNet:スキップコネクションアイデンティモジュールを使うことで残差接続を行い、
深い学習ができるという特徴。8-1-9 Keras1
●Kerasについて
•TensorFlowのラッパーである。
•初心者でも簡単に記述できる。
•複雑なことを行う場合、TensorFlowを書かなければいけない。●Tryの確認
np.random.seed(0)をnp.random.seed(1)に変更
エポック数を100に変更
AND回路, XOR回路に変更
OR回路にしてバッチサイズを10に変更
エポック数を300に変更しよう
☆考察☆
単純なOR回路でもバッチサイズやエポック数によっては、
正解率が100%にならないことがある。XOR回路は、
ハイパーパラメータを変更してもロスが減らず不正解がある。
OR回路は非線形のため、1層ではうまくいかない。●実装実習「分類(iris)」
●Tryの確認
中間層の活性関数をsigmoidに変更しよう
SGDをimportしoptimizerをSGD(lr=0.1)に変更しようソースの修正が必要だった。
# from sklearn.cross_validation import train_test_split
⇒from sklearn.model_selection import train_test_split# plt.plot(history.history['acc'])
# plt.plot(history.history['val_acc'])
⇒plt.plot(history.history['accuracy'])
⇒plt.plot(history.history['val_accuracy'])
☆考察☆
sigmoid関数だと勾配消失を起こすので、
ReLU関数の汎化性の良さはわかるが、irisデータだと分かりづらい。
複雑なデータを扱った際に、それぞれ検証してみようと思う。8-1-10 Keras1
●実装実習「分類(mnist)」
●Tryの確認
load_mnistのone_hot_labelをFalseに変更しよう (error)
誤差関数をsparse_categorical_crossentropyに変更しよう
Adamの引数の値を変更しよう
☆考察☆
model.compileの指定方を修正しないと、上手く動作しなかった。
コーディングのいけないところは、じっくり再確認する予定。
one_hot_labelの設定と、誤差関数をsparse_categorical_crossentropy、
categorical_crossentropyの指定方については間違えないようにする。●実装実習「CNN分類(mnist)」
☆考察☆
確かに処理に時間かかることが確認できた。
padding=SAMEした時の動作比較検証は地道だが面白そう。
多層のconvolutionについてもサイズを変更して確認してみる。●実装実習「cifar10」
☆考察☆
50000枚のトレーニングデータ、10000枚のテストデータで、
カラーの画像をRGBのため255で正規化している。
割愛であるが、処理時間とコードの内容確認のため実施してみた。
動画のように枚数を絞って実行すればよかった・・・。●実装実習「RNN」
2進数足し算の予測
Keras RNNのドキュメント https://keras.io/ja/layers/recurrent/#simplernn●Tryの確認
RNNの出力ノード数を128に変更
RNNの出力活性化関数を sigmoid に変更
RNNの出力活性化関数を tanh に変更
最適化方法をadamに変更
RNNの入力 Dropout を0.5に設定
RNNの再帰 Dropout を0.3に設定
RNNのunrollをTrueに設定
☆考察☆
※BGMがうるさ過ぎて解説の声がすごく聞きづらい。。。
KerasでRNNの実装はすごく楽である。
sigmoidは精度が出ない。状況に応じて使い分けるのは計算させてみてだろうか。
RNNの出力活性化関数をtanhにしたところ、直ぐに収束し精度が良い。
KerasならsimpleRNNから様々なRNNのネットワークに切替えが可能。
Kerasは容易に扱える印象であるが、やはりTensorflowで組めるようにしておきたい。8-2.Section1) 強化学習
8-2-1 強化学習とは
●強化学習とは
長期的に報酬を最大化できるように環境の中で行動を選択
できるエージェントを作ることを目標とする機械学習の一分野。
⇒行動の結果として与えられる利益(報酬)により、
行動を決定する原理を改善していく仕組み。
教師あり学習や教師なし学習とは違った分野。・マーケティングの応用例
プロフィールと購入履歴からキャンペーンメールを顧客に送付するソフト。
行動:顧客ごとに送信、非送信の行動を選択。
報酬:キャンペーンのコスト(負の報酬)、
生み出されると推測される売り上げ(正の報酬)を受ける。☆確認テスト☆
・8-2-1-1 強化学習に応用できそうな事例を考え、
環境・エージェント・行動・報酬を具体的に挙げよ。【自分の回答】
環境:コンビニ等の共通したポイントカード導入箇所
エージェント:ポイントの蓄積・ポイント利用の履歴により、
利用者還元セールやポイント10倍Dayなどを開催する。
行動:顧客のポイントカード利用履歴から、ポイントを還元する、
通常よりポイントを上乗せしてもよいか選択する。
報酬:ポイント還元・上乗せによる負の報酬と、
還元セールや上乗せにより購入が増えると推測される正の報酬。【解答(例)】
ゲームやボードゲーム
プレイヤーが指す手についての強化学習8-2-2 探索と利用のトレードオフ
●探索と利用のトレードオフ
環境について事前に完璧な知識があれば、
最適な行動を予測し、決定することは可能である。⇒どの顧客にキャンペーンメールを送付すると、どの行動するか既知である。
(そんなことはそうそうない。)⇒強化学習の場合、そのような仮定は成り立たないとする。
不完全な知識を元に行動しながらデータ収集し、最適な行動を探索する。●問題になるのは・・・
探索と利用のトレードオフである。「過去のデータで、ベストとされる行動のみを常に取り続ければ、
他にもっとベストな行動を見つけることができない。」
(探索が足りない状態)
↑
トレードオフの関係性
↓
「既知の行動のみ常に続ければ、過去の経験が活かせない」
(利用が足りない状態)どちらの状態も良くなく、トレードオフを上手く調整することが必要。
8-2-3 強化学習のイメージ
●強化学習のイメージ
エージェントがある方策を実施して行動した状態sとなる。
⇒それを観測し、状態sの報酬価値を受け取る。
という流れ。
●関数
方策:方策関数 Π(s,a)で表される。
行動や価値V:行動価値関数 Q(s,a)で表される。8-2-4 強化学習の差分
●強化学習と、通常の教師あり/教師なし学習との違い
【結論】目標が違う
・教師あり/なし学習では、データに含まれるパターンを見つけ出す、
及び、そのデータから予測することが目標
・強化学習では、優れた方策を見つけることが目標8-2-5 強化学習の歴史
●強化学習について
冬の時代があったが、計算速度の進展により大規模な状態を持つ場合でも、
強化学習を可能としつつある。⇒ AlphaGo など●Q学習
行動価値関数を、行動するごとに更新することで学習を進める方法●関数近似法
価値関数や方策関数を関数近似する手法のこと8-2-6 行動価値関数
●行動価値関数とは
価値を表す関数としては、状態価値関数と行動価値関数の2種類がある。⇒ある状態の価値に注目:状態価値関数
状態と価値を組み合わせた価値に注目:行動価値関数●Q学習
行動価値関数を行動のたびに更新することで学習している。8-2-7 方策関数
●方策関数とは
方策ベースの強化学習手法において、
ある状態でどのような行動を採るのかの価値を与える関数のこと。⇒この状態であれば、この行動をとる確率が◎◎%といったもの。
8-2-8 方策勾配法
●方策反復法
方策をモデル化して、最適化する手法
$θ^{(t+1)}=θ^{(t)}+ε∇J(θ)$●Jとは
方策の良さである。
⇒定義しなければならない。●定義方法
・平均報酬:行動をとった時に生まれる価値全部の平均
・割引報酬和:カッコになればなるほど報酬の加算する割合を減らす(減衰)⇒定義に対応して、行動価値関数 Q(s,a)の定義を行い、
方策勾配定理が成り立つ。$∇_θJ(θ)=\mathbb{E}_{π_θ}[(∇_θlogπ_θ(a|s)Q^π(s,a))]$⇒Q関数を使って上記のように定義している。
●例題解説
正解は(a)
方策をアップデートするのが方策勾配に基づくアルゴリズムである。方策勾配定理は基本的には下記の2式から導出される。
・状態価値関数 v(s) = sum_a (π(a|s)Q(s,a))
・ベルマン方程式 Q(s,a) = sum_s’(P(s’|s,a)[r(s,a,s’) + γV(s’)]8-2-9 論文解説DCGAN
●DCGAN
・Deep Convolutional Generative Adversarial Networksという名前。
・CNNのディープなネットワークを使って敵対的学習により画像を生成する。
・例として、実際に存在しないベッドルームの画像をきれいに出力している。
・潜在空間でベクトルとして表現したものからGenerator部分の画像を生成するため、
「笑顔の女性の顔」から「普通の女性の顔」を引いて、「男性の顔」を足し合わせる。
⇒「笑顔の男性の顔」を数式的に扱うことができる。
・Generatorの生成部分はランダムな100個の正規分布の値を使って画像生成している。
⇒生成画像と実際の画像を比較し、Discriminatorというモデルが、
その画像が作られたものかを判定する。8-2-10 Kaggleについて
●Kaggle
・データ分析のコンペティション
・データ分析・AIにおいての世界大会のようなものである。
・Googleが運営している。
・企業等が賞金を出している。
・日本人でも上位に入るチームがある。
・Kaggleへの登録方法。サイトに行けば登録できる。
・コンテスト参加迄の一連の流れ
・Researchが研究目的。
・Featuredが賞金があるコンテスト。
・titanicやmnistなどの初心者向けのコンペがある。
(データセットが有名なため、不正が発生?順位があてにならない)
・Kernelsで世界のデータサイエンティストの実装を参照できる。
・参加した後の流れ
よさそうなスコアのものや説明を読んだり、コピーして動かしてみたり、
データの水増しのやり方を覚えたりすると良い。
・コンペではDiscussionもあるので、知見としてアイディアが共有される。
有意義な議論があり、とても参考になる。
KernelやDiscussionを見てみると良い。
・失敗談
どのコンテストに出るかが難しい。
⇒データセットとタスクの見極め等
データセットの容量が少ないものに出てみるとか、
mnistなどGPUを必要としないものに出てみる等。
Gitを使えれば良いが、スクリプトの管理が難しい。
管理がごちゃごちゃになる。
⇒適当に管理しているといけないのでフォルダで管理する。
・自分一人で頑張ろうとして順位が上がらず、モチベーション低下する。
Kernelを使いこなして参加することで維持できる。
・上位入賞するには、特徴量のパターンが出てきた時に、
1000個と5000個では5000個の方が良い精度が出るので、
時間があれば実践を増やすといい。
シングルモデルは難しく、多数のモデルでアンサンブルが良い。
色々な特徴量を用意して、精度を上げていく。
⇒最後にアンサンブルで多様性を出す。8-2-11 実践につながるインプット
●学習のやり方
プログラミングの習得⇒機械学習
スクリプトベースの学習
Kaggleでの実践⇒実務に活かす。
論文の読み込み。
データ分析やAIはKaggleが良い。
- 投稿日:2020-08-23T13:51:09+09:00
iPadでPythonプログラミングする方法を考える
前置き
Qiita初投稿です.「自分で見返すため」「同様の悩みを持つ人の役に立つため」に投稿できればと思っています.
不慣れで本投稿は文字ばかりです.
徐々に使い方に慣れていこうと思うのでよろしくお願いいたしますm(__)mはじめに
業務ではMatlabを使ってDeep Leaning等やっているのですが、tensorflowの方が自由度も高いし最新のモデルも使える…ということでPython、もっというとtensorflowを手軽に勉強できる環境を構築しようと思い立ち、いろいろ調べてみました。
タイトル記載のわざわざiPadで…というのは家でゴロゴロしながら、あるいは出先でもどこでも自由にコーディング・実行できる環境を作れたらなというだけの理由です。目指す環境
目指す環境はiPad Pro 11inch(2018)を使ってPython3系のコーディング、プログラム実行ができるようになることです.
また,Deep Learningをしたいので,特定のPythonライブラリ(※1)が使用できることも必要条件.また,無料で出来る環境を目指します.少なくともサブスク系は避けたいので,各種クラウドサービス(AzureやAWSなど)は現状検討していません.
(※1) 最低限以下のPythonライブラリは使いたいです.
・numpy
・matplotlib
・tensorflow
・Pillow (Open CVも使いたいがPillowだけでも良いかも)本投稿ではPython環境の候補の調査まで行います.
結論
次章でダラダラと書いているので,先に結論を述べます.
iPadを使って,Python(tensorflow)のコーディング,実行をしたい場合,以下の環境が良さそうだとわかりました.
- "code-server" or "Eclipse Theia"
- "Gitpod"
- "Jupyter Lab"
ただし,Gitpod以外はiPad以外に別途PCを準備する必要があります.
調べてみた感じ,iPad単体でtensorflowのお勉強をする方法は見つからず,いずれの方法もLinux,あるいはWindowsのOS上でPythonを実行させることとなります.
iOS, iPadOS上でPython本体や各種ライブラリを実行させるのはなかなか難しいということでしょう.私はPCもiPadも持っていますが,両マシンの起動が必要ですし制約としてはかなり大きいかもしれません.
調べてみると思ったより面倒だったという次第です.とりあえず,iPad単体で完結させたい場合はGitpodが有力です.
候補となる環境
活用できそうなPython環境をざっくり調べてみました.
本章で各環境についてメモ感覚で記載していきますが,だらだらと書いていますので読み飛ばし推奨です.Pythonista3を購入する
iPadのローカル環境上でPythonを実行できる,Pythonista31というiPadアプリがあります.
¥1,220のアプリで当初の「無料で…」という目標からいきなりブレますが,買い切りのアプリだし評価もかなり高いので悪くないのでは?と思った次第です.しかし…
使えるライブラリに制約があるようで,tensorflowが使えないのでダメそうです.
そもそもiPadのローカル環境上でDeep Learningするのが現実的でないですよね.とはいえ,先に述べたように評価の高いアプリで,手軽にGUIアプリを作ったりできるみたいで凄いアプリみたいです.
本投稿ではこれ以上扱いませんが,気になる方は是非調べてみてください.
* 上記画像はPythonista3の公式サイト2の画像を引用.ブラウザで動くIDEのサーバーをLinuxで立てる("code-server" or "Eclipse Theia")
こちらが本命の方法となりそうです.
Linux環境上でサーバーを立てて,リモートでブラウザからアクセスできるVS CodeライクなIDEがあるようです.
iPadのブラウザから使える,ローカル(iPad)のマシンパワーに依存しない,Linuxの環境上で自由度高く作業できそう,無料,VS Codeのように拡張機能が使える,などの理由から本命だと考えています.code-server3とEclipse Theia4というよく似た2種類のIDEがあります.
よく似ているので「どう違うのか」「どちらが良いのか」は現時点ではわかっていません.(日本語の情報はあまり多くなかったためです).
* 上記画像はcode-serverのGithubレポジトリ3より引用.
VS codeによく似た画面がブラウザ上で扱えます.GitPodを利用する
上述のEclipse Theiaを利用したクラウドのIDEサービスのようです.
クラウドのサブスク系は避けると言っていたのに,またもや目標からブレます.
言い訳すると,制限付きですが無料で利用でき,使い勝手もなかなか良さそうなので候補とした次第です.こちらはGithubアカウントがあれば利用でき,Github上のコードを変更,デバッグしてコミットすることができるようです.
【使い方】
GithubのレポジトリのURLは以下のようになっていると思います.https://github.com/[アカウント名]/[レポジトリ名]↑これを↓以下のように,"gitpod.io/"とつけるだけでgitpodのIDE画面に遷移します.(初回はGitpod利用のためのアカウント紐付けが必要)
https://gitpod.io/github.com/[アカウント名]/[レポジトリ名]アクセスが簡単なので有力な候補です.
ただし長時間利用には課金が必要.軽く試すのには一番良さそうですが自由にがっつりやるとなると課金必須ですので注意してください.
Githubのソースコードを少し修正してデバッグ→コミットみたいな時にベストな気がします.
以下画像のように,こちらもブラウザで使えるVS codeのようなイメージです.
* 上記画像はGitpod公式サイト5より引用WindowsでJupyterサーバーを作成する(Linuxでも可能)
WindowsまたはLinuxサーバーでJupyterサーバーをたてて,iPadのブラウザからアクセスするという方法です.
こちらは,Gitpodやcode-server, Eclipse Theiaのような強力なIDEという訳ではないのですが,Notebook形式(.ipynb)で実行できれば良いという方にはおすすめの方法となりそうです.
実際,Deep LearningするならNotebook形式のほうがデータを見やすいと思うので一番有力かもしれません.どうやら最近ではJupyter NotebookではなくJupyter Labが積極的に開発されている6そうなので,Jupyter Labが良さげですね.
以下画像のように(これもVS Codeに若干似ていますが)ブラウザからアクセスしてPythonのコーディング,実行ができます.ただし,一般的な.pyファイルではなく.ipynbファイルのNotebook形式を扱うことになる点に注意.(.pyファイルも実行できますが,ちょっと使いにくいと思います)
* 上記画像はJupyter Lab公式サイト7より引用最後に
長々と書きましたが,iPadでtensorflowのお勉強というのは割と敷居が高いように感じました.
素直にPCで(あるいはそこそこスペックのノートPCで)やったほうが楽そうです.ただ,なんとか環境構築できればゴロゴロしながらiPadで機械学習のお勉強もできそうだとわかりました.
補足
一番有力候補の"Google Colab"について書くのを失念しておりました!!!
(制限付きで)無料のクラウドサービスですので,おそらく環境構築も不要で最も有力な候補なのですが,しっかり調査できておりません.
従いまして,本投稿内では扱わないこととします.申し訳無いですがご容赦ください.(余裕があれば調査 & 追記いたします.)
Pythonista3のApp StoreのURL:https://apps.apple.com/jp/app/pythonista-3/id1085978097 ↩
Pythonista3の公式サイト:http://omz-software.com/pythonista/ ↩
code-serverのGithubレポジトリ:https://github.com/cdr/code-server ↩
Eclipse TheiaのGithubレポジトリ:https://github.com/eclipse-theia/theia ↩
Gitpodの公式サイトURL:https://www.gitpod.io/ ↩
Jupyter Labについてよく説明してくださっている方がいます.タメになりましたので是非見てください.
https://qiita.com/kirikei/items/a1639954ce5ccaf7ac3c ↩Jupyter Lab公式サイトURL:https://jupyterlab.readthedocs.io/en/stable/index.html ↩
- 投稿日:2020-08-23T13:35:50+09:00
音響シミュレーション FDTD法 Murの吸収境界 導出と実装
はじめに
音響や電磁気を数値シミュレーションする方法の一つにFDTD法があります。これは偏微分方程式の微分を直接に差分に置き換えて計算するもので、理論もプログラムも簡単になる利点があります。
FDTD法は有限の領域を計算するので境界の取り扱いが重要です。
境界を0にしたままにすると固定端となり、波は全反射します。
開けた野外の音響など、無響室のように反射してほしくないときは境界に工夫がいります。
今回は吸収境界の中でもたぶん一番簡単なMurの一次吸収境界を導出し、実装して試してみます。この分野を専門にしているわけではないので、間違っている可能性も十分あります。
その時はコメントで教えていただけるとありがたいです。もとの画像はこんなふうに境界にノイズが乗っていないのですが、オンラインGIF圧縮ツールを使ったらこうなってしまいました。
参考
波動方程式の離散化はこちらを参考にしました。
Qiita:波動方程式の数値解法Murの吸収境界はこちらを参考にしました。
光波の電磁界解析法の現状 時間領域差分法-光学分野への応用を期待して-
FDTD法
波動方程式の離散化
今回は二次元の波動方程式を考えます。
ここで$p$は圧力、$c$は音速です。\frac{\partial^2 p}{\partial x^2} + \frac{\partial^2 p}{\partial y^2}- \frac{1}{c^2} \frac{\partial^2 p}{\partial t^2}=0中心差分で離散化します。
\frac{p^{n+1}_{i,j} - 2p^n_{i,j} + p^{n-1}_{i,j}}{\Delta t^2} = c^2 \left( \frac{p^{n}_{i+1,j} - 2p^n_{i,j} + p^{n}_{i-1,j}}{\Delta x^2} + \frac{p^{n}_{i,j+1} - 2p^n_{i,j} + p^{n}_{i,j-1}}{\Delta y^2} \right)左辺に次の時刻の$p$がくるように式変形します。ここで$\Delta x$と$\Delta y$は等しいことにします。
p^{n+1}_{i, j} = 2p^n_{i,j} - p^{n-1}_{i,j} + \frac{\Delta t^2 c^2}{\Delta x^2} \left( p^n_{i-1,j} + p^n_{i+1,j} + p^n_{i,j-1} + p^n_{i,j+1} - 4p^n_{i,j} \right)FDTDプログラム 固定端
プログラムの作成と実行はJupyter labで行いました。
import numpy as np import matplotlib.pyplot as plt from numba import jit #単位はm,s,m/s #dx = dyにする(式変形でそうしたから) x_len = 8.0 #x方向の長さ m y_len = 8.0 #y方向の長さ m nx = 400 #x方向の格子数 ny = 400 #y方向の格子数 dx = x_len / nx #x方向の格子幅 m dy = y_len / ny #y方向の格子幅 m dt = 0.000001 #時間刻み s c = 340.0 #音速 m/s C1 = (dt**2)*(c**2)/(dx**2) C2 = (c*dt)/dx x = np.linspace(0.0,x_len,nx) y = np.linspace(0.0,y_len,ny) X,Y = np.meshgrid(x,y) if not dx == dy: print("dxとdyを同じにする") if c*dt/dx > 1.0: print("CFL={} < 1".format(c*dt/dx))def get_nearest(xp,yp): """ 音源の置き場所計算用 """ return np.argmin((x-xp)**2),np.argmin((y-yp)**2) sx,sy = get_nearest(4.0,4.0) #音源の位置 @jit def sound_source(p,p_pre,t,f): p[sx,sy] = np.sin(2.0*np.pi*f*t) p_pre[sx,sy] = np.sin(2.0*np.pi*f*(t-dt)) @jit def update(p,p_pre,t): #加振 f = 1.0e3 if t < 1.0/f * 5.0: sound_source(p,p_pre,t,f) p_next = np.zeros_like(p) for i in range(1,nx-1): for j in range(1,ny-1): p_next[i,j] = 2.0*p[i,j] - p_pre[i,j] + C1*(p[i-1,j] + p[i+1,j] + p[i,j-1] + p[i,j+1] - 4.0*p[i,j]) return p_next,pp = np.zeros((nx,ny)) #現在のタイムステップ p_pre = np.zeros((nx,ny)) #1つ前のタイムステップt = 0 img_num = 1 for i in range(50000): if i%200==0: fig,axes = plt.subplots(figsize=(8,8)) axes.imshow(np.flipud(p.T),vmin=-0.1,vmax=0.1,cmap="jet") fig.savefig("anime/{}.png".format(img_num)) plt.close() img_num += 1 p,p_pre = update(p,p_pre,t) t += dt0.2msに1枚グラフを保存してGIMPでアニメーションにしました。
境界を0のままにすると、固定端反射になります。
Murの一次吸収境界 導出
一次元の波動方程式を考えます。
\frac{\partial^2 p}{\partial x^2} - \frac{1}{c^2} \frac{\partial^2 p}{\partial t^2}=0$a^2-b^2=(a+b)(a-b)$の形に因数分解します。
\left( \frac{\partial p}{\partial x} + \frac{1}{c} \frac{\partial p}{\partial t} \right) \left( \frac{\partial p}{\partial x} - \frac{1}{c} \frac{\partial p}{\partial t} \right) = 0上式の第一項は後退波を表しているそうで、反射がないなら0になります。
\frac{\partial p}{\partial x} + \frac{1}{c} \frac{\partial p}{\partial t} = 0これを差分化していきます。空間は$i-\frac{1}{2}$、時間は$n+\frac{1}{2}$の位置で行います。
\frac{p^{n+\frac{1}{2}}_{i} - p^{n+\frac{1}{2}}_{i-1}}{\Delta x} + \frac{1}{c} \frac{p^{n+1}_{i-\frac{1}{2}} - p^n_{i-\frac{1}{2}}}{\Delta t} = 0$i-\frac{1}{2}$や$n+\frac{1}{2}$の位置に格子点はないので平均値を使います。
\frac{ \frac{p^{n+1}_{i}+p^n_{i}}{2} - \frac{p^{n+1}_{i-1}+p^n_{i-1}}{2}}{\Delta x} + \frac{1}{c} \frac{\frac{p^{n+1}_{i} + p^{n+1}_{i-1}}{2} - \frac{ p^n_{i} + p^n_{i-1}}{2}}{\Delta t} = 0あとは式変形して$p^{n+1}_i$を左辺に、それ以外を右辺に持っていきます。
まず両辺に$2c \Delta t \Delta x$をかけて
c \Delta t \left( p^{n+1}_i + p^n_i - p^{n+1}_{i-1} - p^{n+1}_{i-1} \right) + \Delta x \left( p^{n+1}_i + p^{n+1}_{i-1} - p^n_i - p^n_{i-1} \right) = 04種類の$p$があるので、それぞれまとめます。
\left( c \Delta t + \Delta x \right) p^{n+1}_i + \left( c \Delta t - \Delta x \right) p^n_i - \left( c \Delta t - \Delta x \right) p^{n+1}_{i-1} - \left( c \Delta t + \Delta x \right) p^n_{i-1} = 0左辺の第一項以外を右辺に移して
\left( c \Delta t + \Delta x \right) p^{n+1}_i = \left( c \Delta t - \Delta x \right) \left( p^{n+1}_{i-1} - p^n_i \right) + \left( c \Delta t + \Delta x \right) p^n_{i-1}両辺を$\left( c \Delta t + \Delta x \right)$で割って
p^{n+1}_i = \frac{\left( c \Delta t - \Delta x \right)}{\left( c \Delta t + \Delta x \right)} \left( p^{n+1}_{i-1} - p^n_i \right) + p^n_{i-1}無事に参考文献と同じ形の式にできました。
FDTDプログラム Murの一次吸収境界
変更した部分だけ書きます。
def update(p,p_pre,t): #加振 f = 1.0e3 if t < 1.0/f * 5.0: sound_source(p,p_pre,t,f) p_next = np.zeros_like(p) for i in range(1,nx-1): for j in range(1,ny-1): p_next[i,j] = 2.0*p[i,j] - p_pre[i,j] + C1*(p[i-1,j] + p[i+1,j] + p[i,j-1] + p[i,j+1] - 4.0*p[i,j]) #Murの1次吸収境界 for i in range(nx): p_next[i,0] = (c*dt-dx)/(c*dt+dx)*(p_next[i,1]-p[i,0]) + p[i,1] p_next[i,-1] = (c*dt-dx)/(c*dt+dx)*(p_next[i,-2]-p[i,-1]) + p[i,-2] for j in range(ny): p_next[0,j] = (c*dt-dx)/(c*dt+dx)*(p_next[1,j]-p[0,j]) + p[1,j] p_next[-1,j] = (c*dt-dx)/(c*dt+dx)*(p_next[-2,j]-p[-1,j]) + p[-2,j] return p_next,p垂直に入射した波はよく消えますが、斜めに入射したものは少し残ってしまいます。
境界のノイズはGIF圧縮のせいです。Murの二次吸収境界 導出
二次元の波動方程式に対して同様の操作を行えば、Murの二次吸収境界が導出できます。
\frac{\partial^2 p}{\partial x^2} + \frac{\partial^2 p}{\partial y^2}- \frac{1}{c^2} \frac{\partial^2 p}{\partial t^2}=0偏微分記号をたくさん書くのが大変なので、3つの項をそれぞれ$a$,$b$,$c$とおいて式変形します。
$a^2 + b^2 - c^2 = 0$の形を$b^2 - \left( c^2 - a^2\right) = 0$にして、
b^2 - \left[ c^2 \left\{ 1 - \left( \frac{a}{c} \right) ^2 \right\} \right] = 0\left( b + c \sqrt{1- \left( \frac{a}{c} \right) ^2} \right) \left( b - c \sqrt{1- \left( \frac{a}{c} \right) ^2} \right) = 0$y$方向の後退波がない条件は
b + c \sqrt{1- \left( \frac{a}{c} \right) ^2} = 0参考文献はここから一気に式変形が終わってしまうのですが、どうやら平方根の項をテイラー展開で近似しているようです。
$x \ll 1$のとき$\sqrt{1-x^2} \approx 1 - \frac{x^2}{2}$なので
b + c \left\{ 1 - \frac{1}{2} \left( \frac{a}{c} \right) ^2\right\} = 0両辺に$c$をかけて
bc + c^2 - \frac{1}{2} a^2 = 0記号をもとに戻して
\frac{\partial p}{\partial y \partial t} + \frac{1}{c^2} \frac{\partial^2 p}{\partial t^2} - \frac{c^2}{2} \frac{\partial^2 p}{\partial x^2} = 0これがMurの二次吸収境界の条件式になります。
差分化も一次と同様にやろうと思ったら$p^{n+1}_{i-1,j}$など未来の位置の項が残ってしまい、うまくいきませんでした。しかも参考文献の差分化をそのままプログラムしたら発散するし、よくわかりません。
まとめ
FDTD法で重要な吸収境界のうちの一つを導出し実装しました。
回折などより精度が必要な現象を扱うときは、より反射が少ないPML吸収境界を使用するそうです。機会があればそちらも学んで投稿したいと思います。
- 投稿日:2020-08-23T13:25:13+09:00
Python から Excel を編集し、ピボットテーブルを作成する
Python を使って効率化したい
作業効率化のために、 Pandas で作成した Excel ファイルをピボットテーブルを作成し、フィルターの有効化や日時のグループ化をしたいと考えました。
日本語での資料があまりなかったため、ご参考になればと思い共有します。
参考資料に示した URL にピボットテーブルを作成する関数が示されているため、もっと色々なことをしたい場合はそちらを参考にする方が良いと思います。
サンプルファイルの作成
特に意味のないピボットテーブル用のデータを作成します。
エクセルファイルとして吐き出すファイル名を編集して下さい。
指定したファイル名が同一ディレクトリにないよう注意してください。
上書きされても責任はとれません。import pandas as pd import random from datetime import datetime as dt record = [] for y in range(2015, 2020): for m in range(1, 13): for shop in ['A', 'B', 'C']: date = dt(year=y, month=m, day=1).strftime('%Y-%m-%d') price = 200 + random.randint(0,100) record.append([date, shop, price]) df_record = pd.DataFrame(record) df_record.columns = ['date', 'shop', 'price'] df_record['date'] = pd.to_datetime(df_record['date']) df_record.to_excel('ここを編集してください.xlsx', index=None)ピボットテーブル作成
サンプルファイルの作成 で指定したファイル名を、読み込みファイル名にも指定して下さい。
import win32com.client as win32 import os win32c = win32.constants ## win32.Dispatch でもできたが、 pyinstaller で exe 化した際にエラーになったため、 ## win32.gencache.EnsureDispatch を使用したほうが無難かもしれない excel = win32.gencache.EnsureDispatch('Excel.Application') excel.Visible = True ## 読み込み時に絶対パスを指定しなければエラーになる fpath = os.path.join(os.getcwd(),'ここを編集してください.xlsx') wb = excel.Workbooks.Open(fpath) ## Sheet 1 指定し、フィルターを有効にする wbs1 = wb.Sheets('Sheet1') wbs1.Columns.AutoFilter(1) ## ピボットテーブルの作成 wbs2_name = 'pivot' wb.Sheets.Add().Name = wbs2_name wbs2 = wb.Sheets(wbs2_name) pvt_name = 'pvt' pc = wb.PivotCaches().Create(SourceType=win32c.xlDatabase, SourceData=wbs1.UsedRange) pc.CreatePivotTable(TableDestination='{sheet}!R3C1'.format(sheet=wbs2_name), TableName=pvt_name) ## ピボットテーブルの設定 wbs2.PivotTables(pvt_name).PivotFields('date').Orientation = win32c.xlRowField wbs2.PivotTables(pvt_name).AddDataField(wbs2.PivotTables(pvt_name).PivotFields('price'), 'Ave/price', win32c.xlAverage).NumberFormat = '0' wbs2.PivotTables(pvt_name).PivotFields('price').Orientation = win32c.xlPageField ## 日付のグループの選択 ## Periods=(秒, 分, 時, 日, 月, 四半期, 年) wbs2.Cells(4, 1).Select() excel.Selection.Group(Start=True, End=True, Periods=(False, False, False, False, True, False, True)) ## ファイルを閉じる wb.Close(True) excel.Quit()参考資料
How to Create a Pivot Table in Excel with the Python win32com Module



























































































































































