くますきIT日記

IT系資格、競技プログラミングの情報を書いていきます。

Budibase④実装に関するメモ。

 

 

1.本記事について

Budibaseでのアプリ開発をある程度実施して、把握した仕様や注意点を記録する。

※量が多いので、随時追記していく。

 

2.Navigation

 Navigationとは?

 各ページへのリンクを表示する機能。

 リンクはURLで設定する。URL variablesも固定値なら設定可能。
 

②備考

 ーーーーーーーーーーーーーーーー

 便利だが、できないことも多い。

 以下を行うの場合、自分で独自のNavigationを組み込むしかない。

  ・リンクを階層で表示する。

  ・URLやURL variablesを動的にする。

  ・User roles以外で表示、非表示を制御する。

 

 

 練習として、階層型リンクを、開閉できるアコーディオンメニューで作ってみた。

 その際は、以下プラグインを使用した。

 

3.URL variables

①URL variablesとは?

 いわゆるGETパラメータに近い。

 ページ遷移時に、変数を渡すことができる。

 

②備考

 ーーーーーーーーーーーーーーーー

 型はすべて文字列になってしまう。

 「/home/:aa」 という設定で「aa = integerの1」としても、

 型変換しないと文字列として扱われる。配列等も同様。

 文字列以外を渡す場合は、受け取り後に型変換して保持する必要がある。

 同様に「/home/null」としても「nullという文字列」が渡される。

 ーーーーーーーーーーーーーーーー

 ページにURL variablesを設定している場合、

 「URL variables」の数まで一致させないと遷移できない。

 遷移できない場合、エラーも何もなく、ホーム画面に戻される。

 ※もしかするとF12開発者ツールではエラーが表示されるのか?

 なお、URL variablesは空白は認識されない。

  例:「/home/:aa」に遷移したい場合、

    「/home/あ」 では遷移してくれるが、

    「/home/」  では遷移してくれない。(ホーム画面に戻される)

 ーーーーーーーーーーーーーーーー

 

4.Plugin

①Pluginとは?

 拡張機能。標準にないコンポーネントなどを作成できる。

 無料プランは10個まで可能)。

 以下で、どんなプラグインがあるか確認できる。

 

 

5.Action

①Actionとは?

 ボタンクリックや値を更新した際にキックできる処理。

 実施したい処理や、渡す値を指定して使用できる。

 

②備考

 ーーーーーーーーーーーーーーーー

 「execute query」という処理で、BudiBaseに登録したqueryを実行できるが、

 データをselectするqueryを実行した場合、

 後続のActionで実行結果を流用できる。(ここですごく動作を拡張できる余地がある)

 ただ、後続のActionで実行結果を使用する場合、

 「execute query」の順番が変わると、再設定が必要になるので、そこそこ手間。

 ーーーーーーーーーーーーーーーー

 ★重要★

 Actionはあくまでもサーバベースで動作する。(とドキュメントにも記載あり)
 そのため、1つの動作に以下のような2アクションを設定しても動作しない。
 ーーーーー
 ①フォームの値を更新
 ②「①」をフィルタ条件に使用するDP(DateProvider)をリフレッシュ
 ーーーーー
 → 結果、①は動作するが②は動作しない。(更新前の値でフィルタされる)

  なお、同じボタンをもう一度クリックすると、想定通りの②が動作する。

  (1回目のクリックで①の値が更新されているため)

 → 上記のような動作を実施したい場合、

   ダブルクリックさせるアクションにすれば問題ないと思われる・・。

  (1回目のクリックで①の値を更新、2回目のクリックでDBを更新するイメージ)
      ただ、ユーザの手間は少し増える。

 

 ちなみに、以下のような処理は1クリックで動作する。
 ーーーーー
 ①query実行(最新の値をサーバサイドで保持した状態)
 ②フォームの値を「①」の結果で書き換える

 ーーーーー

 →ただ、結局②の値を使用する場合、ダブルクリック的な実装が必要となる。

 

6.参照するDBの制約

①参照するDBに必要に発生する制約

 テーブルは、必ず単一列の主キーを持つ必要がある。複合主キーは不可。

 もし、該当テーブルに単一列の主キーがなければ、

 「ALTER TABLE dummy ADD COLUMN id bigserial;」みたいな

  SQLでキーを作成する必要があり、非常に影響が大きい。

 

 ※なお、Actionでデータを保存(Save Row)するとき、以下の仕様を順守する必要もある。

  ・Insert時:「_id」列に空白文字を渡す。(nullでもよいかもしれない)

  ・Update時:「_id」列に単一列の主キー列の値を渡す。

 

 ※BudibaseDBでテーブルを作成する場合、

  「_id」という一行一位の連番を持つ列が作成される。

 

用する場合、ダブルクリック的な実装が必要となる。

 

7.Data Providerにテーブルでなくqueryを使用する場合の制約

ここが、そこそこ影響が大きい。

①Tableコンポーネントの挙動。

 queryを利用したテーブル項目を作成すると、

 コンポーネント標準のページネーションを利用できない。

 この場合、頑張ってページネーション処理を自作する必要がある。

 

github.com

 

②データのCRUD画面

 queryを利用したテーブル項目を作成すると、

 CRUD画面を自作する必要がある。

 (Field groupコンポーネントを使うと少しだけ楽になる)

 

docs.budibase.com

 

 

 

①参照するDBに必要に発生

 

次回:xxx

 

Budibase③バックアップを設定してみる。

 

 

1.本記事について

Budibaseの環境を構築できたので、バックアップの作成方法を調べた。

 

2.BudibaseのBackupとは

docs.budibase.com

 

 

Budibase自体のユーザ情報やアプリの設定などをバックアップできる。

 

①Budibase自身のユーザ情報等:

 → 世代管理などを含む高度なバックアップは無料プランでは利用できないが、

  CLIでできそう。やってみた内容は後述する。

 

②Budibaseで作成したアプリの設定等:

 → 世代管理などを含む高度なバックアップは無料プランでは利用できないが、

  手動でダウンロードする形のバックアップは可能。



4.バックアップを実施してみる(Budibase自体のユーザ情報等)

Docker版は簡単。

①以下コマンドでバックアップ可能。

 budi backups --export --env .env

ーーーーーーーーーーーー

CouchDB Export
S3 Export
Generated export file - backup-2023-02-26T14:15:47.377Z.tar.gz

ーーーーーーーーーーーー

 

②tarファイルが作成された。

 ls -al

ーーーーーーーーーーーー

-rw-r--r--  1 root root 1238428 Feb 26 14:15 backup-2023-02-26T14:15:47.377Z.tar.gz

ーーーーーーーーーーーー

 

※補足※

 ホストの「.env」ファイルにDBのキーなどが記載されている。

 こんな感じ。(キー部分は適当な乱数に置換している)

ーーーーーーーーーーーー

# This section contains all secrets pertaining to the system
JWT_SECRET=2YjG0oJ2mB7j9u7qabgdjwW6zEcrHUxT
MINIO_ACCESS_KEY=f66I9Ao4M2nYsj2OACgu5CHDBvsk4sTh
MINIO_SECRET_KEY=LxE9PWaMi5GJDIqJ1E8LixbsOxYdN6ub
REDIS_PASSWORD=9sHFDhXEtM1231FfYraWbi7bMNq9iGWM
INTERNAL_API_KEY=mPTDVgJ0NBDdGLk6keZiLHmUeB2IJws
COUCH_DB_USER=admin
COUCH_DB_PASSWORD=YYyQPn3dsaadghjwWuVZAxHrLsvzcmNe3G

ーーーーーーーーーーーー

 

5.リストアしてみる

①以下コマンドでリストア可能。

 budi backups --import <filename> --env <environment file>

 → budi backups --import backup-2023-02-26T14:41:23.066Z.tar.gz --env .env

ーーーーーーーーーーーー

ouchDB Import
MinIO Import
Import complete

ーーーーーーーーーーーー

 

②ログインなどの認証情報がバックアップ時点の内容に戻ったことを確認した。

 ※アプリの設定変更などは戻らない。

6.タスク化してみる

簡単なタスクを作成。とりあえず毎時間作成する。

※実務利用するなら、実行タイミングや保持する世代数も検討必要。

crontab -e
ーーーーーーーーーーーー
0 * * * * budi backups --export --env .env

ーーーーーーーーーーーー

 

次回:本来の目的であるアプリの作成を行ってみる。

 

Budibase②DB環境を構築してみる。

 

 

1.本記事について

AWSにてBudibaseの環境を構築してみたので、データ保管先のDBを準備した。

その備忘録。

 

2.準備したDB環境

実務で想定しているpostgresql-9.6を作成。(古いが・・)

適切なイメージがあったので、これを利用する。

https://hub.docker.com/r/postgresqlaas/docker-postgresql-9.6

# コンテナイメージの取得

docker pull postgresqlaas/docker-postgresql-9.6

※既存DBを使わない、DBにこだわらない場合、

 Budibaseが内包しているDBを利用できる。

 Budibase DB

 

3.BudibaseとDB環境の接続

以下を参考に、Budibaseのコンテナとpostgresql-9.6のコンテナ間の接続を確立する。

accessing a docker container from another container - Stack Overflow

 

①ネットワーク作成

docker network create myNetwork --subnet=172.18.0.0/24

※注意※

サブネットは指定必須。指定しないとランダムなサブネットが割り当てされる

公式ドキュメント参照:

network コマンドを使う — Docker-docs-ja 19.03 ドキュメント

 

②コンテナとネットワークを接続

docker network connect myNetwork postgresql
docker network connect myNetwork bbapps

 

結果は以下で確認した。

docker network inspect myNetwork

-----------------------------------------

        "ConfigOnly": false,
        "Containers": {
            "41cb024e89e0e74c0906fd8b035357eb83f7cb005b4319bff4f036b123015740": {
                "Name": "bbapps",
                "EndpointID": "7896a28f69fd73b4603bb43b2e46d93974c62d56ba9be2ccf5461ccf82738336",
                "MacAddress": "02:42:ac:13:00:03",
                "IPv4Address": "172.19.0.3/16",
                "IPv6Address": ""
            },
            "7b36ed3e27e6257e400afb9c6bc892810395e2a33e667757301e83959c905a7d": {
                "Name": "postgresql",
                "EndpointID": "69786b1e1e8326a1b0eb971bf307da5de2a466a5043e482181457c476285b0bb",
                "MacAddress": "02:42:ac:13:00:02",
                "IPv4Address": "172.19.0.2/16",

-----------------------------------------

 

4.DB環境の展開

①データを永続化するための保管先ディレクトリを作成。

mkdir -p /postgresql

 

②DBの展開

docker run -d --name postgresql -p 5432:5432 -e POSTGRES_USERNAME=test -e POSTGRES_PASSWORD=test_password -e POSTGRES_DBNAME=test -v /postgresql:/data --network=myNetwork --ip=172.18.0.100 --restart=always postgresqlaas/docker-postgresql-9.6

 

色々、入れたい設定を追加した。

1.「-p 5432:5432」ホスト:5432から接続できるようにする。

2.「-v /postgresql:/data」データを永続化するための保管先。

3.「--network=myNetwork」BudiBaseと同じネットワークに配置。

4.「--ip=172.18.0.100」起動時に毎回変わると手間なのでIPアドレスを固定。

5.「--restart=always 」インスタンス起動後、コンテナを自動起動する。

 

③接続確認

# psqlの利用に必要なパッケージをインストール

apt install postgresql-client

# 接続テスト

psql -h 127.0.0.1 -p 5432 -U test 

-----------------------------------------
Password for user test:
-----------------------------------------

→ 問題なく接続できそう。

 

※補足※

本コンテナは、パスワード等未指定の場合、以下で確認可能。

docker logs postgresql

 

5.サンプルDB定義の投入

psqlにて接続して、以下に記載されているサンプルSQLを実行する。

Quickstart: PostgreSQL

 

 

以上で、やっとBudiBaseでアプリを作成できるようになる。

 

次回:BudiBaseのバックアップ設定を行う。

   現状undo機能がないので必須と思われる。※近日実装されるかも。

 

Budibase①AWSにて環境を構築してみる。

 

 

1.本記事について

AWSにてBudibaseの環境を構築してみたので、その備忘録。

※自分のPCのスペック的に、ローカルに構築するのが厳しいため。

 また、AWSの復習もかねて。

 

2.Budibaseとは

budibase.com

いわゆるローコードの開発ツール。

プログラミング言語とか知らない人でも簡単にツールを作成できる。

一度手を出してみたいと思って選定したが、

Budibaseがオープンソースでよさげなので採用した。

 

3.まずはEC2インスタンスの作成

インスタンスタイプはt2.mediumにする。

 メモリ4GBあれば足りるだろう、という推測。

 インスタンスタイプ - Amazon EC2 | AWS

 

②AMIは以下。ubuntu初めてだが何とかなるだろう。

 Canonical, Ubuntu, 22.04 LTS, amd64 jammy image build on 2023-02-08

 なにか問題あれば、OSは後で差し替えする。

 (Budibase自体はDocker版を利用するので問題ないと推測)

 

→ 20時間1ドルくらい。学習中のみ起動するので、費用的にも問題ないはず・・

 

③セキュリティグループの設定。

 Budibaseのデフォルトのポート番号「10000」を、自IPからのみ接続可能にする。

 

④ConsoleはSessionManagerを使用する。

 AWS的に、SSHポートを開放するのは非推奨のため。

AWS Systems Manager Session Manager - AWS Systems Manager

 

インスタンスを起動してSessionManagerで接続できれば準備完了。

 → AWS認定資格の学習がめちゃくちゃ役立っている。

 

4.EC2インスタンスにBudibaseをインストール

 

以下の手順通り、Dockerでインストールを行う。

Budibase CLI Install

※注意※

 BudiBaseアカウント作成後に参照できる以下にも方法が記載されているが、

 必要な情報が不足している。(Ver.14以上のNodeJSが必要など)

 https://account.budibase.app/portal/install/docker

 

①必要なパッケージのインストール

 #準備

 apt update

 #Ver.14以上のNodeJSをインストール

 curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash -
 apt install nodejs

 #結果確認
 node -v → v14.21.3

 #必要なパッケージを追加
 apt install npm
 apt install docker-compose

 

②BudiBaseインストール

 npm install -g @budibase/cli --unsafe

※以下のエラーへの対応として、--unsafe オプションを付与した。

--------------------------------------------

 gyp WARN install got an error, rolling back install
 gyp ERR! configure error
 gyp ERR! stack Error: EACCES: permission denied, mkdir '/usr/lib/node_modules/@budibase/cli/node_modules/bcrypt/.node-gyp'

--------------------------------------------

 

③BudiBase初期化
 budi hosting --init

 

何個か設定の入力を求められるが、問題なく成功した。

--------------------
? This will create multiple files in current directory, should continue? Yes
? Please enter the port on which you want your installation to run:  10000
Configuration has been written successfully - please check /root/.env for more details.
--------------------

 

※ポート番号は「Registered Port Number」の範囲なら何でも良いはず。

TCP/UDPポート番号一覧

 

⑤BudiBase起動

 budi hosting --start

 

数分待ったら完了した。

--------------------
Services started, please go to http://localhost:10000 for next steps.
--------------------

 

⑥疎通確認(EC2インスタンスから接続)

 curl http://127.0.0.1:10000

 

問題なさそう。

-----------------------------------------
Redirecting to <a href="/builder">/builder</a>.root@ip-172-31-36-57:~#
-----------------------------------------

 

⑦疎通確認(自分のPCから)

 WEBブラウザで以下に接続。

  ・http://"EC2インスタンスの「パブリック IPv4 DNS」":10000

 

 ログイン画面が表示されたので、問題なし。

 

⑧管理者アカウントを作成したら、ログインできる。

 これでとりあえずの環境作成は完了。

 

次回:接続先となるDB環境を構築して、Budibaseと接続する。

 

機械翻訳があっても英語を勉強する理由(Google翻訳とDeepLで結果が反対になった話)

最近、AWSの学習中だが、基本的に英語のドキュメントが多い・・。
DeepLとかで一括翻訳して読もうと思ったが、英語の勉強も兼ねて
 ・とりあえず英語で読んでみる
 ・分からない単語や文脈だけ都度調べる

とやっている。

 

すると、少し怖いことがあった。

以下はCloudFormationに関する学習文書。

jayendrapatil.com

 

以下の文章を、Google翻訳とDeepLで翻訳すると意味が真逆になる。

―――――

Stack policies help protect critical stack resources from unintentional updates that could cause resources to be interrupted or even replaced

―――――

 

Google翻訳

―――――

スタック ポリシーは、重要なスタック リソースを意図しない更新から保護し、リソースの中断や置き換えを引き起こす可能性があります

―――――

 

②DeepL
―――――

スタックポリシーは、リソースの中断や交換の原因となる意図しないアップデートから、重要なスタックリソースを保護するのに役立ちます。
―――――

 

確認した結果、DeepLの方が正しいと分かったが、

今後DeepLが100%正しい翻訳をしてくれるわけじゃないと思う。

※無料で使っているので、誤訳があっても、責任を問うつもりは全くない。

 

仕事で技術文書を翻訳かけて読んでいるとして、

急いでいる時、疲れている時、この誤訳に気付けるか。ちょっと怖いと思う。

 

最低限の英語力をつけて、

「この翻訳おかしくね?」と気づけることが必要だと思った。

(CKA CKAD共通)新しいプラットフォームのCKA試験を受けた結果、ひどい目にあったので返金してもらった話

結論

  • 2022年6月から試験プラットフォームが変わっている
  • 日本からの受験時は試験環境が東京リージョンで起動する。
  • 大阪から平日、受験したらネットワーク遅延で試験どころではなかった。
  • 今のこと大阪リージョンの対応予定はないとのこと。

目次

1.自分について

1.1 本投稿の目的

昨年CKADに合格。今年CKAを受験したが、ネットワーク遅延で試験どころではなかった。試験機関に問い合わせた結果、2022年6月から試験プラットフォームが変わっていることが原因と思われるので、その点の共有。

※多分、東京やその付近から受験する場合は問題ないと思っている。

1.2 受験までの経緯

昨年CKADに合格したので、今年はCKAを取ろうと決意して、去年バウチャーを購入。

2022年5月~7月まで勉強して、先日、自宅から試験を受けた。

2022年6月から、試験環境が新しくなる(PSI Bridge)とのことだが、特に問題ないと思っていた。

 

docs.linuxfoundation.org

 
2.1 発生したトラブル①セキュアブラウザ起動後、WEBカメラを変更できない。

(影響:致命的ではない。が、受験が30分ほど遅れた)

新しい基盤での試験は、専用のセキュアブラウザをインストールして利用する。

※他のアプリを立ち上げできなくなったので、不正防止には非常に良いと思った。

ただ、起動時、使用するWEBカメラを1台だけ選ぶ。

私のPCは前面背面、2つのカメラがあったが、試験中は自分を表示するため前面を選択。

これが不幸の始まりだった・・・。

クレジットカード等の証明書をカメラに移す必要があるが、

前面のカメラではピントが合わない。(背面は画質が良いので一瞬でピントを合わせることができる)

 

チャットにて、英語で「助けて!WEBカメラ切り替えさせて!」と言っても

特に対応してもらえず。方法も教えてもらえず。

やむなく、こちらから強制的にセキュアブラウザを落として、背面カメラを指定した。

 

が、背面カメラでは、自分を映しながら試験を行う事は不可能。

急遽、外付けディスプレイを用意して、PCは後ろ向きにして受験することになった。

(=外付けディスプレイが無ければ受験不可能だった・・・)

 

ただ、本トラブルは、以下の機能を調べて、利用すれば対応できた可能性はある。

・セキュアブラウザでのカメラ切り替え(方法があるなら)

・PCのカメラのピント合わせ等

 

致命的なのは次のトラブルだった。

 

2.2 発生したトラブル②ネットワーク遅延がすごすぎて試験にならない

新しい試験プラットフォームでは、

セキュアブラウザから、リモートデスクトップ環境(ubuntu)に接続して作業する。

厄介なのが、以下が、リモートデスクトップ環境からのみ可能な点だ。

・ドキュメントの閲覧

・コマンドの実行

・メモ帳によるコマンドの作成

 

セキュアブラウザに以下の2画面を表示するイメージだ。

 ブラウザの左半分:問題の表示

 ブラウザの右半分:リモートデスクトップ環境の表示

 

ここで何が起こったかと言うと・・・ずっと遅いのだ。

リモートデスクトップ環境だけが。

マウスのクリック、スクロール、キーの入力。全てに3~6秒ほどタイムラグがある。

一番最悪なのは、ドキュメントの閲覧。

画面のスクロールが、1スクロール10秒以上要する。

実質、ドキュメントを参照できない。

試験の後半1時間はさらにひどく、感覚的に上記の約1.5倍の遅延となった。

 

ここでも、チャットで助けを求めても、何も対応してもらえない。

ブラウザをリフレッシュしろ、と言われたが、何回リフレッシュしても変わるわけがない。

当然だ、ブラウザの左半分は全く問題ないのだ。

明らかに、ブラウザの右半分、リモートデスクトップ環境だけ遅い。

 

結果、試験の進行はひどかった。

120分中、60分ほど、待ち時間だった。何もできなかった・・。

 

私のネットワークに問題ない、という証拠はある。

 試験前:youtubeでFHDの動画見ながら学習。特に遅延なし。

 試験後:速度測定のサイトに接続して速度測定→100M/bpsという結果。

あきらかにリモートデスクトップ環境に問題があったのだ。

 
3.1 試験結果と問い合わせ

試験結果が届いたが、64/66で不合格。当然、納得できるわけがない。

 

調べた結果、新しいプラットフォームにて、ネットワーク遅延に関するトラブルが色々あるようだった。

(①リモートデスクトップ環境が、試験場所と異なるリージョンで起動される問題※修正済み)

training.linuxfoundation.org


(②試験中、通信が遅すぎる・・みたいな話)

I had the worst experience during de CKA exam because of the awful psi plataform. : kubernetes

 

linuxfoundationに質問することにした。

jira.linuxfoundation.org

 

3.2 問い合わせの回答

やり取りを要約した結果は以下の通り。

※連絡~回答は1サイクルで2営業日ほど要する。

以下のため、非常にストレスがかかった。

 ①途中、質問の誤回答があったが、それに関する説明が一切ない。

 ②こちらの環境の責任にしてくる。(明確な根拠を書いているのに・・!と思った。)

 

――――――

質問の概要:

 リモートデスクトップ環境が遅すぎる?どのリージョンで起動した?

――――――

(linuxfoundation,以下lf)

 受験時、タイムゾーンに「Asia/Japan」を指定してたね!

 結果、日本外のリージョンでリモートデスクトップ環境が起動したよ!

 ネットワークが空いている時間帯に受験してね!

 無線LANは接続が不安定だよ!

 ブラウザの動作が遅かった場合、画面の解像度などを下げてね!

(私)

 どのリージョンで起動したの?

 日本のリージョンに対応する予定はありますか?

 この状態は、バウチャー購入時に無かった情報であり、

 昨年CKADを受験したときも発生していなかった問題なので、

 対応予定がなければ返金していただきたいです。

 日本は島国だから、他のリージョンで起動してたら、海をまたぐ通信になるので遅くなると思います。

 私の方のネットワークや環境の原因にしないでください。

(lf)

 リモートデスクトップ環境は、東京リージョンで起動してたよ!

 試験中、常にネットワーク遅延が発生していて、pingのレスポンスに200ミリ秒以上を要していたよ。

 試験後半は、1000ミリ秒を超えることもあったよ!

 ブラウザの動作が遅かった場合、画面の解像度などを下げてね!

(私)

 さっきと回答違いますね。私は大阪から受験しました。大阪~東京は、数百キロあるので、

 その距離が遅延の原因ですよね?大阪リージョンで起動する方法を教えてください。

 あと、二度と、私の方のネットワークや環境の原因にしないでください。

 以下により、リモートデスクトップ環境に起因した遅延と特定しています。

 ①試験前:Youtubeで高解像度の動画を、遅延なく閲覧できていました。

 ②試験中:リモートデスクトップ環境以外(試験問題)は問題なく参照できました。

 ③試験後:インターネットの速度測定サービスにて確認した結果、100M/bpsの速度でした。

 最後に、pingが1000ミリ秒以上要するって、大変な遅延ではないですか?その状態で作業した事はありますか?

(lf)

 大阪リージョンを指定する方法は、ないよ!(タイムゾーンで指定したリージョンで起動するよ!)

 今後も東京リージョンで起動する場合、返金するよ!

 回答が間違っていたのは、初めは一般的な回答、その次に詳細に確認した回答を行ったからだよ!

 今回は、ネットワーク遅延が原因なので、無料で再受験できるようにするよ!

(私)

 回答が一般的とか、一般的でないとかどうでもいいです。

 間違ってたのに、訂正の一言もないのですか?

 再受験しても遅延するなら意味が無いです。

 1回の受験に2時間要する事はご存じですよね?

 もう質問する意味がないので、返金していただけますか?

(lf)

 返金するよ!

 

3.3 現在の状況

 返金待ちの状態。

 学習した時間や試験時間、試験用の会議室の予約料、

 すべて無駄になるので悔しいが、損切りすることにした。

 

3.4 気になる事

単なるクレームでなく、他の地域から受験した場合の動作が気になります。

リモートデスクトップ環境は東京リージョンで起動するので、

 東京や関東での受験なら問題ない?

・他の地域でも、インターネットが空いている時間、例えば深夜や早朝なら問題ない?

 

以上

資格試験に合格したので勉強法を残しておく:E資格

結論

  • 勉強時間は250時間。→過剰だったかも。
  • 受験費が高い(最低33,000円。+ 認定講座が高い)。

目次

1.自分について

1.1 本投稿の目的

E資格(JDLA Deep Learning for ENGINEER 2022 #1)に合格したので、

勉強方法の備忘録。

1.2 受験前の知識
  • PGは実務経験あり(Java, PHP)。Pythonはほぼ未経験。
  • 文系出身なので数学の知識は高校レベル。
1.3 受験理由

何年か前、「AIを使えば、ある文書と類似する文書を表示する」とかできるのでは?と考えて失敗し、大量の時間を無駄にした。

→ 知識が全くなく、ググって出た「~モデルを使って~してみた」を

 コピペして試す、の繰り返し。中身を一切できていないので改善もできず、失敗から何も得ることもできず。

 → この反省から「AIを理解すればもう少しまともな方法とれたのでは?」と考えて、受けようと決めた。

 

2.勉強

2.1 認定講座の選定

目的:受験資格を得ること。
この試験は、大学の単位に近い物があり、まず、受験資格を得る必要がある。

 

認定講座は色々あるが、結構高い。(12万円~50万円くらい)

www.jdla.org

 

まず、専門実践教育訓練、という制度を発見した。

これに該当する講座は、最大70%、国がお金を出してくれるらしい。

なので、50万円→自己負担15万円、というイメージ。

※一応、普通の会社員なら、2~3年に1回だけ使える制度。

 事前にハローワークで申請必要なので、その時、聞くのが良いはず。

www.mhlw.go.jp

 

ただ、今回は見送った。

専門実践教育訓練を利用するにはキャリアカウンセリングを受ける必要があり、

 ・ハローワークで受ける:

   無料だが、基本は平日の日中しか予約できない。

 ・企業や個人(キャリアカウンセラー?)などで受ける:

   有償だが(1万円くらい?)、土日夜間でも受けれる。

 

コロナによる保育園休園

 → 子供の家庭保育、で有給が無いのだ・・。試験費高いからお金も抑えたい。

 

ということで、以下を受けてみた。

初期費用2.2万円、月額3千円で受けれるサービス。

半年くらいなら、5万円くらいで受講できる。

※宣伝ではない。少なくとも、今の時点では・・←

 値段だけで決めて色々困ったので、後でデメリットを色々書く。

ai999.careers

 

2.2 認定講座の受講(約150-200時間)

 

上記の講座[ラビットチャレンジ]を半年受けた。

基本的には、以下を4セット実施(応用数学機械学習、深層学習1、深層学習2)。

  1. 講座(動画)を見る。
  2. 受講した証明のため、ブログに内容 + 自分の考えを書く。
  3. 一定数の講座完了後、確認テストを合格する。

→ 3が大変で、4択問題だが、95%正解しないと、次に進めない。

 問題が多いと、以下のような内容になる。

  問題数  :100問

  必要な点数:95点

 さらに、

  一定回数(10回目?)以上の受験:5回4千円の追加課金。

  誤答の開示:1回4千円の追加課金。

 

 これで、誤答の開示を2回実施した。つまり、約8千円追加で費用が発生した。

 費用を抑えるためにこの講座を選んだのだが・・。

 (まあ、それでもトータルでは、他の講座より格段に安いが・・) 

 

2.3 認定講座が提供する模擬試験の実施(約30.0時間)

これは、価値があった。

 ・模擬試験

 ・出てきそうな問題に重点を置いた動画

 ・JDLAが作成した公式例題

があり、実際の試験で、結構な割合で類似の問題が出てきた。

さらに、「JDLAが作成した公式例題」の知識で回答できる問題も数問あった。

(実際の試験内容は書けないルールなので書かない)

 

3.受験

3.1 受験
  • 講座の受講完了後、できるだけ早く受験センターを予約すること。
    試験日が金~土曜日だが、最悪金曜日しか申し込みできなくなる。
  • 受験後、結果は三週間待つ必要がある(オンライン受験なのになぜ?と思ったが・・)。

→2時間で全問回答。結構ギリギリで完了。

 ※とりあえず一周。時間がかかる問題は後から確認するべき。

  あと、メモ用のホワイトボードは早めに交換してもらう。

  3~4回交換してもらった。(イレーサー貸してくれたらいいのに・・)

3.2 結果確認

2月19日受験で約三週間後(3月11日)、メールが届いた。

f:id:you_it_blog:20220311010445p:plain

 

→合格。良かった。平均80%くらい?。60%がボーダーという情報があるが実際は不明。

 落ちたら金銭面がまずいので助かった。

4.最後に

4.1 シラバスの改定について

次回(2022年8月)以降、シラバスが大きく変わるらしい。

www.jdla.org

※「詳細な試験範囲はこちら」を参照

 

4.2 今回選んだ講座について

今回選んだ講座については、本当に安かろう微妙かろうだな、と思った。

メリット:

 ①安い。

 ②模擬問題がある

 ③講師が選んだ重点説明の動画がある。

  →とにかく①が強い。多分。②③はどの講座にもあるのでないか。

デメリット:

 ①確認テストが辛い

  正解率95%が必要、一定回数以上の実施、誤答の開示が有償

  → まあ、難しい問題とは思う。無制限に受講できて誤答の開示が無料なら、

   力ずくで100%とることも可能なので・・。

 ②質問できない(不明点は自分で解決してください。だから安価です、という形)

  → まあ、HP上でも書かれているので、これに文句を言うのはおかしいか。

 ③資料(画像)とテキストが一部違う。

  → 資料と選択肢の変数名が違っている場合があり、

   何回か「これ何?」となった。これは結構いらいらする。

 ④シラバスの改定について、事前の情報提供が無かった。

  → これ、信頼関係的に一番疑問に思ったかもしれない。

    基本的に、E資格の受験資格は2年間保たれるので、受験資格を得た後、即解約しても良い。

   今回落ちたら、次の試験はシラバス改定後になるので、

   一部講座の再受講が必要になる(必須でないが受けないと試験で対応できない)が、月額制でない講座は、そのあたりも無料で継続受講できる救済措置がある。

   しかし、ラビットチャレンジは月額制なので、その分、単純に利用月が増える=出費が増えるのだ。

   月額制という特徴を踏まえたら、受講者に一言説明が必要では?と思った。

 

4.3 もし次受けるなら

講座は変えるかもしれない。色々調べたが、これが良いかも。

s.avilen.co.jp

 

全人類が分かる・・なので、落ちたらどうしようと思うが・・。

※宣伝ではないので、各自、絶対に適切な講座を調べた方が良い。

 人により、何を優先するか違うはず。

  ・費用を抑える(サポートが弱いので、自分で色々調べる必要がある)

  ・サポートを充実させる(費用は高くなるが、合格サポート、とかもある)

  ・専門実践教育訓練を使う(申請が色々大変だが、使えるならありがたい)

 

誰かの参考になれば、うれしいです。 

 

※記載していないですが、文部科学省の資料(行列計算)なども参考になりました。

 コメント頂いたら情報を追記するようにします。

 

以上。

E資格の勉強⑥深層学習day4

目次

本投稿の目的

深層学習(day4)に関する学習のまとめ

Section1:強化学習

【要点】

強化学習

 最終的な報酬を最大化する、というエージェントを作ることを目的とした機械学習

 → 競技プログラミングで例えると動的プログラミングのイメージ。
 例:顧客が100人存在するとして、誰にキャンペーンのメールを送るか。

   上記の場合、「キャンペーンの売り上げ - 送るコスト」 を最大化するようなエージェントを作成する。

   ・ 全員に送ると送るコストが不要に大きくなる。

   ・ 全員に送らないとキャンペーンの売り上げがない。

   → 最適な行動を見つける必要がある。

 

【実装演習】

 実装演習が無いため、以下サイトを参考に、演習を行った。www.tcom242242.net

 

~問題の設定〜

 

――――――――――――――――――――――――

演習①4×4の迷路。ゴールに到着=報酬100。トラップに到着=報酬-100。

――――――――――――――――――――――――

情報:迷路の状態

self.filed_type = {
"N": 0, # 通常
"G": 1, # ゴール
"W": 2, #
"T": 3, # トラップ
}
self.map = [[3, 2, 0, 1],
[0, 0, 0, 2],
[0, 0, 2, 0],
[2, 0, 2, 0],
[0, 0, 0, 0]]

情報:使用した設定

# 定数
NB_EPISODE = 100 # エピソード数
EPSILON = .1 # 探索率
ALPHA = .1 # 学習率
GAMMA = .90 # 割引率
ACTIONS = np.arange(4) # 行動の集合

 

実行結果

f:id:you_it_blog:20211122232808p:plain

→ 4×4のシンプルな迷路であるため、20回目ほどでエージェントが最大の報酬を獲得できるようになっている。

 ※試行回数をエピソードと呼ぶ。

 

――――――――――――――――――――――――

演習②4×5の迷路。(迷路を大きくする。トラップの数も増やす)

――――――――――――――――――――――――

情報:迷路の状態

def __init__(self):

self.filed_type = {
"N": 0, # 通常
"G": 1, # ゴール
"W": 2, #
"T": 3, # トラップ
}
self.map = [[3, 2, 0, 3, 0],
[0, 0, 0, 2, 0],
[0, 0, 2, 0, 1],
[0, 0, 0, 0, 0]]

情報:使用した設定

# 定数
NB_EPISODE = 100 # エピソード数
EPSILON = .6 # 探索率 ※.1で確認した結果が良くなかったため修正。
ALPHA = .1 # 学習率
GAMMA = .90 # 割引率
ACTIONS = np.arange(4) # 行動の集合


実行結果①

f:id:you_it_blog:20211122234533p:plain

→ 50回目くらいで、ようやく最適解を得れるようになった(難しくなった)

 

実行結果②探索率.1の場合

f:id:you_it_blog:20211122234932p:plain

→ 最適解にたどり着けないまま終了している。

 ※パラメータ設定の重要性が分かる結果となった。

 

【関連記事レポート】

以下サイトには、実装演習のみでなく理論も記載されている。

www.tcom242242.net

強化学習エージェントにて行動選択に使用される関数の説明も読み込んでおくべき。

 ・ε-greedy行動選択

  ε-greedy法とは~制御工学の基礎あれこれ~
  →上記サイトが分かりやすかった。まずはランダムに選んで、

   結果を確認してから最適解を探していく・・というまさに貪欲法の手法。

 ・softmax行動選択

  【強化学習】softmax行動選択

  → 高期待値の選択肢を選ぶ確率を上げていく手法。

 

Section2:AlphaGo

【要点】

AlphaGo:

 Google DeepMindが開発した、囲碁AI。※

 教師有り学習と強化学習を使用して、3つのネットワークを学習させている。

 ※AlphaGo(Lee)は囲碁だが、後継のAlphaGoZeroは将棋やチェスも可能とのこと。

 

www.sbbit.jp

 

Alpha Go の学習ステップ:
①PolicyNetの教師あり学習
 教師データ:3000万局面分の棋譜データ。教師と同じ手を指せるように学習。
 ※教師1、その他0とした19×19の配列を分類問題として学習させたとのこと。

②PolicyNetの強化学習
 PolicyNetとPolicyPool(500イテレーション単位で強化学習の結果を保管した物)で対局を行い、その結果を用いた方策勾配法で学習。
 ※ミニバッチ学習(単位:128)を1万回実施したとのこと。

③ValueNetの学習
 PolicyNetで対局を行い、途中まで①のモデル、途中から②のモデルを使用。
 その勝敗結果をラベルとした教師データを作成して学習。
 ※ミニバッチ学習(単位:32)を5000万回実施したとのこと。

 

【実装演習】

実装演習が無いため、以下サイトを参考に、演習を行った。

PythonでAlphaZeroを実装する場合のサンプル・・探すのに時間を要した。

 囲碁の盤面(19×19)でなく、Connect4(6×7)の実装。※Connect4:4目並べ

github.com


(Google翻訳アドオンで日本語に訳している。今回はgoogle colaboratoryを使用。pipの対象バージョンを若干変えないと動かない・・)

f:id:you_it_blog:20211123212506p:plain

実行結果(ニューラルネットワークの学習状態を確認)

f:id:you_it_blog:20211123212430p:plain

 

【関連記事レポート】

AlphaGoの作成元であるdeepmindのページを読み込んだ。

deepmind.com

 

・NNの内「ポリシーネットワーク」は、次に再生する動きを選択する。
  もう1つのNNである「バリューネットワーク」は、ゲームの勝者を予測する。
  → 概要であるが、各NNの役割が記載されている。
・AlphaZero:チェス、将棋、囲碁のゲームをマスターする方法をゼロから学ぶ、かつ世界チャンピオンのコンピュータープログラムを打ち負かす、単一のシステム。
  → 要点、にも記載している内容。AlphaZeroは「Go」でない→ 囲碁以外でも利用できる。
・MuZeroとして知られる最新バージョンのアルゴリズムは、AlphaZeroのパフォーマンスに匹敵すると同時に、
  ゲームのルールの説明なく、視覚的に複雑なゲームに対応する。
  → まだ開発初期の段階とのことであるが、より複雑なゲームにも対応できるモデル「MuZero」が開発中とのこと。

 

Section3:軽量化・高速化技術

【要点】

高速化:

 分散深層学習:並列で学習を行うことで学習の時間を短縮する。

軽量化:

 寄与度の低いパラメータの削除、パラメータの精度の削減などで精度を維持しつつ、メモリの使用量などを削減する。

 

――高速化1:並列化――

①データ並列化:

 ワーカー(学習に使用する端末)にモデルをコピー。

 データを分割して、各ワーカーで並列に学習を行う。

 同期型:

  全てのワーカーから結果が返ってくるまで待つ。

  結果が帰ってから、平均の勾配を計算してマスターとなるモデル(親モデル)を更新。その後、各ワーカーが最新のマスターを使用して学習を行う。

 非同期型:

  各ワーカーから結果が返ってき次第、マスターに勾配を反映。

  各ワーカーは、順次最新のマスターを使用して学習を行う。

 

 → 同期型は遅いが精度が高い。非同期型は早いが精度が安定しない。

  現在は同期型が主流とのこと。

 

②モデル並列化

 親モデルを分割して各ワーカーにコピー。(中間層を分割するイメージ)

 各ワーカーで並列に全てのデータを学習する。

 

→データが多い場合がデータ並列化。

 モデルが大きいときはモデル並列化。を使用するべき。

 

――高速化2:GPU――

GPU:元々は画像描画のための演算器。CPUより個々の性能が低いが並列処理は強い。

 → 並列化との相性が非常に良い。

 

――軽量化1:量子化――

パラメータの精度を落とす。(例:64bit浮動小数点 → 32bit)

NNはパラメータ数が膨大であるため、単純に半分にするだけでも効果が大きい。

なおかつ、64bit浮動小数点 → 32bit程度では精度が落ちない。

※落としすぎると極端に精度が落ちる。適切な調整が必要。

 

――軽量化2:蒸留――

高精度のモデルを基に、新たな軽量のモデルを作成する。

※高精度のモデルを教師に使用するイメージ。高精度のモデルの予測 と 新たなモデルの結果 の差異を利用して、新たなモデルの重みを更新する。

 

――軽量化3:プルーニング――

刈り込み、という意味。一定より重みが低い(= 寄与度の低い)パラメータを消してしまう方法。

※かなり大胆な削除も可能で、全体の90%近くのパラメータを削除 → 精度は90%以上を維持できる、という例もある。

 

【実装演習】

実装演習が無いため、以下サイトを参考に、演習を行った。

※テーマは色々あるが、今回は「量子化」の確認を行った。

www.tensorflow.org

 

量子化(64bit → 16bit)の効果を確認する。

f:id:you_it_blog:20211123221812p:plain

 

実行結果

INFO:tensorflow:Assets written to: /tmp/tmpqrhrrf6i/assets
INFO:tensorflow:Assets written to: /tmp/tmpqrhrrf6i/assets
WARNING:absl:Buffer deduplication procedure will be skipped when flatbuffer library is not properly loaded
Float model in Mb: 0.08052444458007812 ← 量子化前。
Quantized model in Mb: 0.02333831787109375 ← 量子化後。(サイズが1/4となっている)

 

【関連記事レポート】

www.tensorflow.org

 

――注目した部分――

重要度に基づいて重みのプルーニングを行い、トレーニング プロセスの過程でモデル内の複数の重みを徐々にゼロに指定することで、モデルのスパース性を実現します。スパースモデルは圧縮しやすく、ゼロの部分については推論の際にスキップできるため、レイテンシを改善できます。

この手法では、モデルの圧縮により改善が行われます。将来的には、フレームワークでこの手法をサポートすることで、レイテンシを改善する予定です。モデル圧縮により、精度の低下を最小限に抑えながら、最大で 6 倍の改善が確認されました。

→ 高速化、軽量化、には様々な手法が存在するが、将来的には特に実装を意識しなくても、手法を利用できるようになると思われる。※少なくとも、プルーニングについては将来的にTensorFlowでフレームワーク化されるとのこと。

 

 

Section4:応用モデル

【要点】

以下の3つのモデルについて記載する。

 ・MobileNet

 ・DenseNet

 ・WaveNet

 

――MobileNet――

軽量化・高速化・高精度化を実現した画像認識のモデル。

スマートフォンなどで利用できる軽さが強み。(名前の由来?)

→深さ別の畳み込み、と点別の畳み込み、の組み合わせで軽量化している。

 

・深さ別の畳み込みのイメージ(1チャネル1フィルタ)

※資料が分かりずらかったので、処理数の削減が分かるように紫の線と囲みを追加。 

f:id:you_it_blog:20211123234725p:plain

 

・点別の畳み込みのイメージ

※資料が分かりずらかったので、処理数の削減が分かるように紫の線を追加。

f:id:you_it_blog:20211123233818p:plain

 

通常の畳み込みの代わりに、上記の2つの畳み込みを使う事でほぼ同じ処理を高速に行っている。(Depthwise Separable Convolution)

以下の図が分かりやすい。

f:id:you_it_blog:20211123235047p:plain

 

 

――DenseNet――

NNでは中間層が増えるほど、前の層の学習が難しくなる。(=勾配消失問題)

その対策を行ったモデルがDenseNet。

 

以下の様に、後半の中間層の入力に、前半の入力層の出力を使用している。

→ 逆伝搬の際、後半の中間層からダイレクトに前半の入力層に繋がる道がある。

 → 経由する層を抑えつつ、先頭の層に逆伝搬を行うことができる。

f:id:you_it_blog:20211123235506p:plain



 

――WaveNet――

音声波形を作成するモデル。(Waveフォーマットが由来?)

特徴として、時系列データを畳み込むことで、広い範囲のデータを入力に使用している。(= 受容野を増やしている。)結果、時系列を考慮した非常に適切な出力を行うことができている。この畳み込みを「Dilated Convolution」と呼ぶ。

 

f:id:you_it_blog:20211124215312p:plain

 

【確認テスト】

――①(あ)に当てはまる単語を選択する――

深層学習を用いて結合確率を学習する際に、効率的に学習が行えるアーキテクチャを提案したことがWaveNet の大きな貢献の1 つである。

提案された新しいConvolution 型アーキテクチャは(あ)と呼ばれ、結合確率を効率的に学習できるようになっている。

 ・Dilated causal convolution
 ・Depthwise separable convolution
 ・Pointwise convolution
 ・Deconvolution

→正解は一番上の「Dilated causal convolution」

 

――②(い)に当てはまる単語を選択する――

(あ)を用いた際の大きな利点は、単純なConvolution layer と比べて(い)ことである。

 ・パラメータ数に対する受容野が広い
 ・受容野あたりのパラメータ数が多い
 ・学習時に並列計算が行える
 ・推論時に並列計算が行える

→正解は一番上の「パラメータ数に対する受容野が広い」。

 比較的少ないパラメータで、広い範囲の時系列を考慮した出力を行うことができる。

 

【実装演習】

実装演習が無いため、以下による演習を行った。

※今回はMobileNetを対象にした。

 

Google Colab(MobileNet)

 

試した点

元々のプログラムは「パンダの画像をパンダと判定する」内容であるが、

動作の確認のため「猫の画像」に変更した。

f:id:you_it_blog:20211124214654p:plain

使用した猫の画像(パンダと同様にWikipediaの画像を使用)

 

実行結果

f:id:you_it_blog:20211124214847p:plain

――――――――――――――――――――――――

INFO:tensorflow:Restoring parameters from mobilenet_v2_1.0_224.ckpt
Top 1 prediction:  282 tabby, tabby cat 0.6503355

――――――――――――――――――――――――
画像を「tabby cat(トラ猫)」と判定できている。

 

【関連記事レポート】

MobileNetに関する資料(V2のリリースの記事)

shiropen.com

――注目した部分――

MobileNetV2は、レイテンシ、サイズ、精度をトレードオフし、バッテリー消費を低減した低消費電力を実現しており、小規模、低遅延、低電力のモバイルファースト・コンピュータビジョンモデルとして機能させます。

TensorFlow-Slim Image Classification Libraryの一部としてリリースされます。クラウドに送るのではなく、モバイル上でニューラルネットワークを実行する利点としては、セキュリティ、プライバシ、レイテンシが緩和されること、そして、いつでもどこでもアクセスできるユーザーエクスペリエンスの向上が言えます。

→ MobileNetは軽量化・高速化・高精度化を実現した画像認識のモデル。と記載したが、その目的はここ。サーバへデータを投げることなく、スマートフォンなどの端末で機械学習が完結できるのであれば、サーバにデータを送り、処理を依頼する必要が無くなる。結果、通信の遅延やセキュリティの問題を気にする必要が無くなる。極端な話、オフラインでも利用する事ができるようになる。

 

Section5:Transformer

【要点】

Transformer:

 Seq2seqよりも高速かつ高精度な翻訳に利用できるモデル。

 Attentionを利用するのみで、RNNを利用しない。

 Encoder-Decoder Model。Encoderで入力をencode → encode結果をDecoderでDecoderする。(どちらも6層を持つ)

Attention:

 文中の単語の意味を理解する際に、どの単語をキーとすればよいか、という情報。

 例:it という単語は単体では解釈できない。前後の単語(human、he、penなど)をキーとする必要がある。

 

【実装演習】

実装演習が無いため、以下による演習を行った。

Transformerのチュートリアル(提供元:TensorFlowコミュニティ)

ポルトガル語を英語に翻訳するチュートリアル

 

実行結果

f:id:you_it_blog:20211124223803p:plain

比較:Google翻訳の結果

f:id:you_it_blog:20211124223908p:plain

→ 比較的簡単な文章であるものの、ポルトガル語を適切に英語に翻訳できている。

 

【関連記事レポート】

japan.zdnet.com

――注目した部分――

Googleは米国時間5月18日、自然言語分野における最新のブレークスルーとして、自然な会話を実現する新たな言語モデル「LaMDA」(Language Model for Dialogue Applications:対話アプリケーション用の言語モデル)について発表した。
最近の「BERT」や「GPT-3」といった言語モデルと同様に、LaMDAは「Transformer」をベースにしている。TransformerはGoogle Researchが生み出したニューラルネットワークアーキテクチャーであり、2017年にオープンソース化されている。

→ Transformerは2017年にオープンソース化してから、2021年、5年後の最新のモデルのベースにも使用されている。そのため、Transformerの動作の基礎を抑えておくことは、とにかく最新のモデルの仕組みを抑える、という方法よりも有益と思われる。

 

Section6:物体検知・セグメンテーション

【要点】

物体検知:

 画像の中から、物体の場所、種類、数を検知する技術。

 分類、物体検知、意味領域分割、個体領域分割などに分けることができる。

 ※それぞれのイメージは、確認テスト①を参照すること。

 

物体検知のデータセット

 VOC12、ILSVRC17、MS COCO18、OICOD18等、様々なデータセットが存在する。

 ※データセット:この場合、分類対象の画像や正解(ラベル)をまとめた物。

  同じデータセットに対する結果 = モデルの性能を客観的に比較できる。

  ただし、実務で使用するモデルを選ぶ際などは、用途に応じたデータセットに対する結果を参考にすること。

  例えば、オークションの画像(≒ 中央に1つの物体)を識別するために、

  自然の写真(≒ 様々な場所に様々な物体)に対する精度が高いモデルを使用しても、

  想定通りの精度は得られない。

 

評価指標:

 評価指標として、実際の結果(True or False) × 分析結果(True or False)の4パターンの

 要素が土台となる。以下は必ず覚える必要がある。 

f:id:you_it_blog:20211124230053p:plain

 

 クラス分類:

  出力は「~が存在する確率※(0~1の範囲)」となる。

  そのため、「~が存在すると断言する」閾値が変われば、同じモデルでも結果が変わる。

 物体検出:

  出力は「何が、どこに、どれくらいの確率※(0~1の範囲)で存在するか」となる。

  ※厳密には確率ではない・・。

 

物体検出の場合は、IoUという指標も評価に使用される。

一言で説明すると、「予測と実際の積結合 / 予測と実際の和結合」 の値。これも0~1の範囲となる。

 

FPS

 物体検知の場合、精度だけでなく速度も問題となる。

 例:分析に100ミリ秒等を要するモデルの場合・・

    定期的に物体の数を集計したい場合 → 十分な速度。

    自動運転で障害物を検知したい場合 → 遅すぎる。

 速度の指標として「FPS:Flames per Second」が存在する。

 一言で説明すると、「1秒間で何枚の画像を処理できるか」

 

物体検知のフレームワーク

 大分類すると以下の2つに分類できる。

  2段階検出器:

   候補領域の検出とクラス推定を別々に行う。高精度だが遅い。

   → まず画像から物体を抜き出し、その後物体を分類、というイメージ。

  1段階検出器:  

   候補領域の検出とクラス推定を同時に行う。精度が安定しないが早い。

   → 画像から物体の抜き出しと分類を同時に行うイメージ。

 

【確認テスト】

――①それぞれの物体認識タスクにおける出力は何か?――

f:id:you_it_blog:20211124224725p:plain

 

→分類:

  画像に対する単一or複数のラベル。

  例:風船、窓、木など。

 物体検知:

  各物体の範囲を示す四角形

  例:各風船を囲む四角形

 意味領域分割:

  各物体に対するピクセル単位のクラスラベル

  例:風船に対する色付け

 個体領域分割:

  各物体に対するピクセル単位のクラスラベル

  例:風船に対する色付け。なおかつ、風船ごとに異なる色を付ける。

    (各風船を区別する)

 

【実装演習】

実装演習が無いため、未実施。

代替として、資料に記載されている確認テストを一通り学習した。

 

【関連記事レポート】

物体検知のフレームワーク(YOLO)の情報

ichi.pro

――注目した部分――

CarND車両検出は、 Udacity自動運転車Nanodegreeプログラムのプロジェクトです。このプロジェクトの目的は、ダッシュカメラのビデオで車両を検出することです。この実装では、バッチ処理なしで21FPSを実現できます。

→ リアルタイム検知の重要性。例えば完全な自動運転の場合、

 ①物体検知(例:障害物がある)

 ②適切な処理の選択と実行(例:ブレーキペダルを押す)

 ③実際に動作が反映される(例:車が減速する) という流れになるが、

 「①物体検知」が一番ボトルネックになると思われる。自動運転の完全化には、物体検知の速度の向上が一番重要なのではないだろうか。(もちろん精度も重要)

 

以上

 

 

 

E資格の勉強⑤深層学習day3

目次

本投稿の目的

深層学習(day3)に関する学習のまとめ

Section1:再帰ニューラルネットワークの概念

【要点】

再帰ニューラルネットワーク

 時系列データに対応可能なニューラルネットワーク

 時系列データ=データに前後関係がある。例えばボードゲーム

 今の盤面は「直前(一手前)の盤面」の延長。さらに「直前(一手前)の盤面」は「直前(二手前)の盤面」の延長・・。

 この時系列を考慮するために、3つの重みを使用する。

 ①入力→中間層の重み。

 ②入力→出力層の重み。

 ③ひとつ前の中間層→中間層の重み。(ここがRNNの特徴)

 この3つの重みを時系列データの開始時点→終了時点まで再帰的に処理する。

 ※技術者的には「recursive neural network = RNN」と覚えるとよさげ。

 

BPTT:

 時間をさかのぼる誤差逆伝搬。

 といっても特殊な事ではなく、微分の連鎖率を使用して、

 「最後の時間の誤差」→「最後-1の時間の誤差」・・→「最初の時間の誤差」

 を何度も求めることなく少ない計算で求めること。

 

【確認テスト】

RNNのネットワークには大きくわけて3つの重みがある。

1つは入力から現在の中間層を定義する際にかけられる重み、

1つは中間層から出力を定義する際にかけられる重みである。

残り1つの重みについて説明せよ。

(回答)

 【要点】に記載した③の部分。ひとつ前の中間層→中間層の重み。

 

【演習チャレンジ:再帰ニューラルネットワーク

以下は再帰ニューラルネットワークにおいて構文木を入力として再帰的に文全体の表現ベクトルを得るプログラムである。ただし、ニューラルネットワークの重みパラメータはグローバル変数として定義してあるものとし、_activation関数はなんらかの活性化関数であるとする。木構造再帰的な辞書で定義してあり、rootが最も外側の辞書であると仮定する。(く)にあてはまるのはどれか。

(1)W.dot(left + right)

(2)W.dot(np.concatenate([left, right]))

(3)W.dot(left * right)

(4)W.dot(np.maximum(left, right))

 →答え:(2)。木構造のルートの右側と左側の一覧を全て抜き出し、結合したリストを活性化関数に使う。※「+」や「*」をしてしまうと、単語間の前後の繋がりを失ってしまう。

 

【演習チャレンジ:BPTT】

左の図はBPTTを行うプログラムである。

なお簡単化のため活性化関数は恒等関数であるとする。

また、calculate_dout関数は損失関数を出力に関して偏微分した値を返す関数であるとする。(お)にあてはまるのはどれか。

(1)delta_t.dot(W)

(2)delta_t.dot(U)

(3)delta_t.dot(V)

(4)delta_t* V

 →答え:(2)。過去にさかのぼるたびにUを掛ける必要がある。

 

【実装演習】

サンプルプログラムの実行結果。

①サンプルプログラムをそのまま実行。(中間層の活性化関数=シグモイド関数)

iters:0
Loss:1.4592344781314095
Pred:[1 1 1 1 1 1 1 1]
True:[0 1 1 0 1 1 1 0]
59 + 51 = 255
------------
iters:100
Loss:1.0581959125913671
Pred:[0 1 1 0 0 0 0 0]
True:[1 0 1 0 0 0 1 1]
47 + 116 = 96
------------
iters:200
Loss:0.8673602168782221
Pred:[0 1 1 0 0 0 1 0]
True:[0 1 0 0 0 0 1 1]
12 + 55 = 98
------------



------------
iters:9800
Loss:0.0012348486845701505
Pred:[1 1 0 0 0 1 0 1]
True:[1 1 0 0 0 1 0 1]
116 + 81 = 197
------------
iters:9900
Loss:0.0011690369308675372
Pred:[1 0 1 0 0 0 0 1]
True:[1 0 1 0 0 0 0 1]
120 + 41 = 161

→最終的に、誤差が0.001近くまで減少している。そして予測[Pred]と答え「True」が全て一致している(=正しく学習できている)。

 

②中間層の活性化関数をシグモイド関数 → ReLuに変更してみた。

iters:0
Loss:1.877133925079352
Pred:[0 0 0 0 0 0 0 0]
True:[1 0 0 1 0 0 1 1]
83 + 64 = 0
------------
iters:100
Loss:1.4036311687506768
Pred:[1 1 0 1 1 0 0 0]
True:[1 0 0 1 0 0 0 0]
104 + 40 = 216
------------
iters:200
Loss:1.0
Pred:[1 1 1 1 1 1 1 1]
True:[0 1 1 1 1 0 1 1]
6 + 117 = 255
------------



------------
iters:9800
Loss:2.0
Pred:[1 1 1 1 1 1 0 1]
True:[1 0 1 0 1 0 1 1]
117 + 54 = 253
------------
iters:9900
Loss:2.25
Pred:[1 1 1 1 1 1 0 0]
True:[0 1 1 0 0 0 0 0]
92 + 4 = 252
------------

→誤差が減っていない。最終的な精度も良くない。

 (=勾配の消失か発散が発生している?)

 誤差の推移を見た結果、大きな上下を繰り返している。

 勾配の消失?おそらく違う。消失なら、誤差が概ね一定になるはず。

 勾配が発散?おそらく当たっている。勾配爆発が発生していると考えられる。

(誤差の推移)
――――――――――――――――――――――――――

f:id:you_it_blog:20211107212139p:plain

――――――――――――――――――――――――――

 

Section2:LSTM

【要点】

RNNの課題:

 時系列が多い → 中間層が多い、という状態と同じ。

 →時系列が長いほど、初めの部分が出力層から遠くなる。

  →勾配消失問題が発生する。

   →活性化関数の変更や正則化などの対応と異なり、構造自体の変更で対応したものがLSTM。

 

LSTM:

 以下の部品を使用する。

  ・CEC勾配を1とした自己ループを行うゲート(勾配が1なら勾配は消失も発散もしない)

  ・入力ゲート、出力ゲート:CECの欠点(学習が行えない)に対応するため、設けられた層。

  ・忘却ゲート:CECが保持している情報の内、不要となった情報を削除するための層。

 

【確認テスト:RNNの課題】

シグモイド関数微分した時、入力値が0の時に最大値をとる。

その値として正しいものを選択肢から選べ。

(1)0.15

(2)0.25

(3)0.35

(4)0.45

 →答え:(2)。最大でも0.25なので、例えば3回さかのぼる場合、勾配は最大でも0.25^2≒0.0015まで小さくなる。

  中間層(RNNの場合時系列)が多いほど勾配が消えることが分かる。

 

【確認テスト:LSTM】

以下の文章をLSTMに入力し空欄に当てはまる単語を予測したいとする。

文中の「とても」という言葉は空欄の予測においてなくなっても影響を及ぼさないと

考えられる。このような場合、どのゲートが作用すると考えられるか。

「映画おもしろかったね。ところで、とてもお腹が空いたから何か____。」

 →答え:忘却ゲート。

 

【演習チャレンジ:RNNの課題】

RNNや深いモデルでは勾配の消失または爆発が起こる傾向がある。

勾配爆発を防ぐために勾配のクリッピングを行うという手法がある。

具体的には勾配のノルムがしきい値を超えたら、勾配のノルムをしきい値に正規化するというものである。

以下は勾配のクリッピングを行う関数である。(さ)にあてはまるのはどれか。

(1)gradient * rate

(2)gradient / norm

(3)gradient / threshold

(4)np.maximum(gradient, threshold)

 →答え:(1)。値が大きすぎる(ノルムを超える)場合、正規化されるという内容から推測できる。

 

【演習チャレンジ:LSTM】

以下のプログラムはLSTMの順伝播を行うプログラムである。

ただし_sigmoid関数は要素ごとにシグモイド関数を作用させる関数である。

(け)にあてはまるのはどれか。

(1)output_gate* a + forget_gate* c

(2)forget_gate* a + output_gate* c

(3)input_gate* a + forget_gate* c

(4)forget_gate* a + input_gate* c

 →答え:(3)。

 

Section3:GRU

【要点】

LSTMの課題:

 パラメータ数が多く、計算の負荷が高い。この課題に対応するための構造がGRU。

GRU:

 ゲート付き回帰ユニット。リセットゲート、更新ゲートと呼ばれる2つのゲートを持つ。(LSTMより1つゲートが少ない)

 LSTMと同等以上の精度、かつパラメータ(重み)の数を減らした構造。

 

【確認テスト:LSTMの課題】

LSTMとCECが抱える課題について、それぞれ簡潔に述べよ。

 →答え:

   LSTM:パラメータ数が多く、計算の負荷が高い。

   CEC:学習ができない。(結果、入力、出力ゲートが必要になる)

 

【確認テスト:GRU】

LSTMとGRUの違いを簡潔に述べよ。

 →答え:ゲート数が異なる。(LSTM:3ゲート、GRU:2ゲート)

     また、GRUの方が軽量である。

 

【演習チャレンジ】

GRU(Gated Recurrent Unit)もLSTMと同様にRNNの一種であり、

単純なRNNにおいて問題となる勾配消失問題を解決し、長期的な依存関係を学習することができる。

LSTMに比べ変数の数やゲートの数が少なく、より単純なモデルであるが、

タスクによってはLSTMより良い性能を発揮する。以下のプログラムはGRUの順伝播を行うプログラムである。

ただし_sigmoid関数は要素ごとにシグモイド関数を作用させる関数である。

(こ)にあてはまるのはどれか。

(1)z * h_bar

(2)(1-z) * h_bar

(3)z * h * h_bar

(4)(1-z) * h + z * h_bar

 →答え:4。新しい中間状態は、1ステップ前の中間表現と計算された中間表現の線形和で表現される。つまり更新ゲートzを用いて、(1-z) * h + z * h_barと書ける。

 

Section4:双方向RNN

【要点】

双方向RNN:

 双方向、つまり過去だけでなく未来の情報も考慮することで精度を向上させるモデル。文章の翻訳などに使用される。(文章の場合で説明すると、翻訳に「直前の文脈」だけでなく、「直後の文脈」も使用しよう、というモデル)

 

 

【演習チャレンジ】

以下は双方向RNNの順伝播を行うプログラムである。

順方向については、入力から中間層への重みW_f, 一ステップ前の中間層出力から中間層への重みをU_f、逆方向に関しては同様にパラメータW_b, U_bを持ち、両者の中間層表現を合わせた特徴から出力層への重みはVである。

_rnn関数はRNNの順伝播を表し中間層の系列を返す関数であるとする。

(か)にあてはまるのはどれか

(1)h_f + h_b[::-1]

(2)h_f * h_b[::-1]

(3)np.concatenate([h_f, h_b[::-1]], axis=0)

(4)np.concatenate([h_f, h_b[::-1]], axis=1)

 →答え:4。まず、「+」や「*」では前後の特徴が混ざってしまう。=concatenateを使用するべき。次に、「h_f(過去→未来)」のデータと「h_b[-1](未来→過去の反転)」のデータを結合するため、axis=1とする。これにより、例えば1,2,3というデータの場合、以下のような行列を作成できる。

 [1(過去→未来方向)、1(未来→過去方向)],

 [2(過去→未来方向)、2(未来→過去方向)],

 [3(過去→未来方向)、3(未来→過去方向)]

 

【参考】

引数(axis)のイメージ:

deepage.net

 

Section5:seq2seq

【要点】

seq2seq:

 Encoder-Decoderモデルの一種。以下2つの深層学習モデルで構成される。

  ・入力を中間表現(圧縮したベクトル)に変換(encode)するモデル(Encoder-RNN)。

  ・中間表現(圧縮したベクトル)を変換(decode) して出力を作成するモデル(Decoder-RNN)。

 

Encoder-RNN:

 入力(例えば、テキストデータ)を、単語等のトークンに区切って渡す。

 Taking:文章を単語等のトークン毎に分割し、トークンごとのIDに分割する。

 Embedding:上記のIDから、そのトークンを表す分散表現ベクトルに変換する。

Decoder-RNN:

 Encoder-RNNの個々の出力を受け取り、出力するデータを生成する。

 

seq2seqの課題:

 最終の入力に対する一問一答しかできない。それまでの文脈などが考慮できない。

 →HRED、VHRED、VAE等の会話モデルがある。

 

HRED:

 過去n-1の入力から次の出力を生成できる。

 →最終の入力が「はい」や「いいえ」でも、直前の入力から適切な出力が行える可能性がある。(seq2seqより人間らしいやり取りができる)

 →課題。同じ流れの会話には同じ回答しかできない。短い回答(Yes、No)などを選びがち。

 

VHRED:

 HREDに、VAEの潜在変数の概念を追加して、HREDの課題に対応したもの。

 

VAE:

 Variational Autoencoder(変動オートエンコーダー) 。

 データを潜在変数zの確率分布という構造に押し込めることができる。

 (以下のリンクを読むと分かる) 

qiita.com

 

【確認テスト:seq2seq】

下記の選択肢から、seq2seqについて説明しているものを選べ。

(1)時刻に関して順方向と逆方向のRNNを構成し、それら2つの中間層表現を特徴量として利用するものである。

(2)RNNを用いたEncoder-Decoderモデルの一種であり、機械翻訳などのモデルに使われる。

(3)構文木などの木構造に対して、隣接単語から表現ベクトル(フレーズ)を作るという演算を再帰的に行い(重みは共通)、文全体の表現ベクトルを得るニューラルネットワークである。

(4)RNNの一種であり、単純なRNNにおいて問題となる勾配消失問題をCECとゲートの概念を導入することで解決したものである。

 →答え:2。(1は双方向RNN。3は純粋なRNN。4はLSTM)

 

【確認テスト:VHRED】

seq2seqとHRED、HREDとVHREDの違いを簡潔に述べよ。

 →答え:

  seq2seqとHRED:seq2seqは一問一答。HREDは直前の入力を使用した出力が可能。

  HREDとVHRED:HREDは短い回答が多い。また、同じ流れの場合同じ回答。VHREDはVAEにてHREDの課題に対応する。

 

【演習チャレンジ:seq2seq】

演習チャレンジ機械翻訳タスクにおいて、入力は複数の単語から成る文(文章)であり、それぞれの単語はone-hotベクトルで表現されている。

Encoderにおいて、それらの単語は単語埋め込みにより特徴量に変換され、そこからRNNによって(一般にはLSTMを使うことが多い)時系列の情報をもつ特徴へとエンコードされる。

以下は、入力である文(文章)を時系列の情報をもつ特徴量へとエンコードする関数である。ただし_activation関数はなんらかの活性化関数を表すとする。

(き)にあてはまるのはどれか。

(1)E.dot(w)

(2)E.T.dot(w)

(3)w.dot(E.T)

(4)E * w

 →答え:1。Eは単語の埋め込みの一覧表(word embedding matrix)。単語ごとの特徴ベクトルが書かれた表のイメージ。この特徴ベクトルと重みを掛けた値を返せばよい。

 

【確認テスト:VAE】

VAEに関する下記の説明文中の空欄に当てはまる言葉を答えよ。

自己符号化器の潜在変数に____を導入したもの。

 →答え:確率分布z∼N(0,1)

 

Section6:Word2vec

【要点】

word2vec:

 文字は人間が作成した単なる記号であり、金額や色(RGBA)、物のサイズのような大小関係や連続性が無い = 文字のままではNNに使用できない。

 各単語をone-hotベクトル※に変換する必要がある。が、世界中の全単語をone-hotベクトルする事は物理的に不可能、かつ、one-hotベクトルでは単語の類似度などを把握できない。

 ※one-hot ベクトル:1つの成分が1、残りの成分は全て0のベクトル。

 word2vecは「単語の確率分布は、周辺の単語によって決定される」という分布の仮説に基づいて、単語をone-hotベクトルでないベクトルに変換する方法。

 

Section7:Attention Mechanism

【要点】

Attention Mechanism:

 sec2secは中間表現(圧縮したベクトル)を使用して出力を作成する。

 →中間表現(圧縮したベクトル)はサイズが決まっているので、入力が短い文章でも、長い文章でも使用できるベクトルの次元数は同じ。

  →長文に弱い。(表現を持ちきれない)

   →中間表現(圧縮したベクトル)を使用して出力を作成するタイミングで、元々の入力を参照できるようにする方法。

 

【確認テスト】

RNNとword2vec、seq2seqとAttentionの違いを簡潔に述べよ。

 →答え:

  RNNは時系列データに対応可能なニューラルネットワーク。処理対象だけでなく、処理対象の前のデータ(中間層の出力)も用いて、処理に使用する。

  ※直前~現在の流れを考慮した処理を行える。

  word2vecは文章(単なる人が作成した記号であり、NNで利用するにはベクトルに直す必要がある)をone-hot-ベクトルでなく、単語ごとの関連性を持たせたベクトルに変換する手法。

  seq2seq:Encoder-Decoderモデルの一種。2つのNNを持ち、文字に対する一問一答が可能である。

  Attention:seq2seqの課題(長文に弱い)に対応するために、seq2seqのDecoderへの入力として、「Encoderの成果物」に加えて、「入力」も使用して、入力データに柔軟なを可能とする

E資格の勉強④深層学習day2

目次

本投稿の目的

深層学習(day2)に関する学習のまとめ

Section1:勾配消失問題

勾配消失問題

【要点】

勾配消失問題:

 誤差伝搬法では、パラメータの更新量は「出力層 → 入力層」方向に計算していく。

 しかし、パラメータの更新量 = 傾きが0になる値を微分で求めるが、

 活性化関数に「シグモイド関数」を使用している場合、入力値が大きいと傾きがほぼ0になり更新量が消えてしまう。

 結果、階層(入力層に近い層)のパラメータが一切更新されなくなり、学習が止まってしまう。

 これが勾配消失問題。

 

【考察結果】

確認テスト1:シグモイド関数微分した時、入力値が0の時に最大値をとる。その値として正しいものを選択肢から選べ。

(1)0.15
(2)0.25
(3)0.35
(4)0.45

(回答)

 (2)0.25

(補足)

 シグモイド関数:f(x) = [1 / (1 + exp^x)]

 シグモイド関数微分:f'(x) = f(x)(1−f(x))

 → これにx=0を代入すると、0.5× (1-0.5) = 0.25

 数値の0乗 = 1になるため、簡単に計算できた。

 ※最大でも0.25と小さい。

  仮に、入力値が「5」の場合、微分結果は「0.00664・・」まで小さくなる。

  → パラメータの更新量がほぼ0となってしまう。

  

keisan.casio.jp

 

勾配消失問題の解決法

【要点】

複数の解決方法が存在する。

 ①活性化関数の選択:

  ReLu関数を使用する。

    入力が0以下 :0

    入力が0を超える:入力

   → 微分結果が大きくなるので、勾配消失を防止できる。

 ②重み(W)の初期値設定

  Xavier(ザビエル)を使用する。
   → 重みの要素を、前層のノード数の平方根で割った値

 ③バッチ正規化

  ミニバッチ単位で、データを正規化(最大1、最小0)する。

 

【考察結果】

確認テスト1:重みの初期値に0を設定すると、どのような問題が発生するか。簡潔に説明せよ。

(回答)

 重みの初期値に0を設定(正しく表現すると、重みに同じ値を設定する)と

  順準伝搬の結果が同一となる

   → 逆伝搬法による更新量も同一となる

    → 全く同じ動作をするノードが複数存在することになる。

     (ノードを多数持つ意味が無くなってしまう)

 

確認テスト2:一般的に考えられるバッチ正規化の効果を2点挙げよ。

(回答)

 ①ミニバッチごとに発生する入力データの差を抑制できる。

  →ミニバッチごとの学習のブレを(過剰や過少な学習)を防止できる。

   →学習の速度と精度の向上を期待できる。

 ②入力の分布によっては、勾配消失が発生する可能性がある。

  →入力データを適切な範囲に変換することで、適切な更新量を維持できる。

   →勾配消失問題の抑制。

(参考)

https://www.renom.jp/ja/notebooks/tutorial/basic_algorithm/batch_normalization/notebook.html

ichi.pro

 →考察:バッチ正規化の目的 = バッチごとにバラつく可能性がある入力を安定させて、学習も安定させてしまおう、という考え。

 

Section2:学習率最適化手法

【要点】

 学習率:

  更新量を反映させる際の割合。適切な値を設定する必要がある。

   学習率が大きすぎる場合:

    → 最適解にたどり着かない。

     ※ふり幅が大きすぎる振り子のイメージ。

   学習率が小さすぎる場合:

    → 最適解にたどり着つまでに時間を要する。局所最適解から動けなくなる。

      ※ふり幅が小さすぎる振り子のイメージ。

 

  → 基本的な方針として、学習率を動的にして、

    初めは大きく、学習が進むにつれて小さくする。

 

 学習率最適化手法:

  学習率を調整する方法。

   ・モメンタム(慣性):勾配降下法の調整に加えて、以下を加算する。

    → 絶対値[現在 - 前回の重さ] × 慣性(前回動いた分の慣性が働くイメージ)

   ・AdaGrad

   ・RMSProp

   ・★Adam★ ←最も主流の手法。モメンタムとRMSPropの長所を持っている。

 

【考察結果】

確認テスト1:モメンタム・AdaGrad・RMSPropの特徴をそれぞれ簡潔に説明せよ。

 (回答)

 ・モメンタム:

  学習率が一定。最適解に近づく時間が早い。大域的最適解に移動できる。

 ・AdaGrad:

  学習率が可変。モメンタムより事前設定必要なハイパーパラメータが少ないため、設定が容易。

  (モメンタム=学習率と慣性。AdaGrad=学習率のみ)

  学習が進むほど学習率が低下する。鞍点問題※の問題がある。

  ※馬の鞍のように、なだらかな地点(精度が上がる点が遠くにある)場合、

   学習を行えなくなる問題。(学習量が小さい → 精度が上がる点までたどり着けない → 学習できない)  

 ・RMSProp:

  学習率が可変。AdaGradを改善した物。

 

【演習】

SGD

(実行結果)

f:id:you_it_blog:20211020160552p:plain

→ 学習データ、検証データ共に精度が上がらない。

 

(実行結果※バッチ正規化あり)

f:id:you_it_blog:20211020162232p:plain

→ ある程度改善した。60%の割合で正解できる。

 

②momentum

(実行結果)

f:id:you_it_blog:20211020160816p:plain

→ 学習データ、検証データ共に精度が上がらない。

 

(実行結果※バッチ正規化あり)

f:id:you_it_blog:20211020162327p:plain

→ 大きく改善した。(90%近い精度)

 

③AdaGrad(momentumのアルゴリズムを基に作成してみた)

(作成したアルゴリズム)

for key in ('W1', 'W2', 'W3', 'b1', 'b2', 'b3'):

# ===========================================
# momentum
# ===========================================
# if i == 0:
# h[key] = np.zeros_like(network.params[key])
# h[key] = momentum * h[key] - learning_rate * grad[key]
# network.params[key] += h[key]
# ===========================================
# AdaGrad
# ===========================================
if i == 0:
h[key] = np.full_like(network.params[key], 1e-4)
else:
h[key] += np.square(grad[key])
network.params[key] -= learning_rate * grad[key] / (np.sqrt(h[key]))

(実行結果)

f:id:you_it_blog:20211020163238p:plain

→ 学習データ、検証データ共に精度が上がらない。

 

(実行結果※バッチ正規化あり)

f:id:you_it_blog:20211020162737p:plain

→ 大きく改善した。(80%の精度)

 

④RMSProp

(実行結果)

f:id:you_it_blog:20211020163152p:plain

→ バッチ正規化なしでも、非常に高い精度。

 

⑤Adam

(実行結果)

f:id:you_it_blog:20211020160459p:plain

→ バッチ正規化なしでも、非常に高い精度。

Section3:過学習

【要点】

過学習については、機械学習で学習済み。(忘れている場合、機械学習のレポートを参照する)

ここでは、「正則化 = 過学習を防止する方法」について、記載する。

 ・L1正則化、L2正則化
  誤差関数に各ノルムを加えて重みを抑える方法。ノルムは以下が参考になる。

  ※L1ノルム:ダイヤ型(マンハッタン距離)、L2ノルム:円(ユークリッド距離)と認識しておく。
manabitimes.jp

 

 ・ドロップアウト

  ノードをランダムに削除して学習させる。

  ※一般的には隠れ層(中間層)の場合は50%ほどのノードを無効化するとよい、とのこと。

sonickun.hatenablog.com

 

【考察結果】

確認テスト1:線形モデルの正則化の手法の中にリッジ回帰という手法があり、その特徴として正しい物を選択しなさい。

 (a)ハイパーパラメータを大きな値に設定すると、全ての重みが限りなく0に近づく。

 (b)ハイパーパラメータを0に設定すると、非線形回帰となる。

 (c)バイアス項についても、正則化される。

 (d)リッジ回帰の場合、隠れ層に対して正則加工を加える。

 

(回答)

 (a)ハイパーパラメータを大きな値に設定すると、全ての重みが限りなく0に近づく。

(考察)

 リッジ回帰(L2ノルム)のハイパーパラメータを大きくする → 罰則が大きい → 重みが小さくなる。

 

確認テスト2:下図について、L1正則化を表しているグラフはどちらかを答えよ。

f:id:you_it_blog:20211020225627p:plain

(回答)

 L1ノルム = マンハッタン距離なのでダイヤ型。答えは右の図。

 

【演習】

過学習が発生しているデータ。

 → 練習用データの精度は高いが、テスト用データの判定率が低い。

f:id:you_it_blog:20211020231127p:plain

 

②L2正則化

f:id:you_it_blog:20211020231301p:plain

 

③L1正則化

f:id:you_it_blog:20211020231412p:plain

 

ドロップアウト

パターン1:ドロップアウト割合=15%

 →比較的、適切に学習できるようになっているが、最終的に精度が乖離(≒過学習)となっている。

f:id:you_it_blog:20211020231458p:plain

 

パターン2:ドロップアウト割合=50%

 →全く学習が進んでいない。(ドロップアウトしすぎている)

f:id:you_it_blog:20211020233158p:plain

 

ドロップアウト + L1正則化

パターン1:ドロップアウト割合=8% かつ 正則化強度=0.004

 →L2正則化に近い形となっている。

f:id:you_it_blog:20211020231658p:plain

 

パターン2:ドロップアウト割合=12% かつ 正則化強度=0.006 (パターン1の1.5倍)

 →精度を上げ切れていない。正則化が強すぎると思われる。

f:id:you_it_blog:20211020233635p:plain

 

Section4:畳み込みニューラルネットワーク(CNN)の概念

【要点】

CNN:画像や動画認識で広く使われるモデル。以下のような構造を持つ。

 ・入力層→畳み込み層→プーリング層→全結合層→出力層

ja.wikipedia.org


※学習のターゲットとして、LeNetを題材としている。

ja.wikipedia.org

 

【各層の説明】

畳み込み層:

 3次元の空間画像も学習できるような層。

 出力 = 活性化関数(入力 * フィルター(≒重み) + バイアス)

 ★用語★

 バイアス:

  バイアス項と同じ。

 パディング:

  入力(中途半端なサイズ)を処理しやすいサイズに調整する。(埋める)

  調整分は0埋めか、周囲と同じ値などを設定する。

 ストライド

  フィルターの移動量。

 チャンネル:

  入力を判定するフィルターの数の様な物。異なる複数のフィルターを使用して、

  識別性能を向上させる。

 

プーリング層:

 入力(=畳み込み層の出力)から、特定の値を取得する。(最大値や平均値)

 単語の意味を把握すると覚えやすい。

 

 

※プーリング:統計学には「グループをたばねる」という意味。

toukeigaku-jouhou.info

 

【考察結果】

確認テスト1:サイズ6×6の入力画像を、サイズ2×2のフィルタで畳み込んだ時の出力画像のサイズを答えよ。なお、ストライドとパディングは1とする。

 (回答)

 5×5

 (イメージ)

以下の★部分が縦横1マスずつ動くイメージ。

――――――

★★〇〇〇〇

★★〇〇〇〇

〇〇〇〇〇〇

〇〇〇〇〇〇

〇〇〇〇〇〇

〇〇〇〇〇〇

――――――

 

【演習】

★畳み込み層★

・畳み込み層の実装

'''
input_data: 入力値
filter_h: フィルターの高さ
filter_w: フィルターの横幅
stride: ストライド
pad: パディング
'''
def im2col(input_data, filter_h, filter_w, stride=1, pad=0):
# N: number, C: channel, H: height, W: width
N, C, H, W = input_data.shape
out_h = (H + 2 * pad - filter_h)//stride + 1
out_w = (W + 2 * pad - filter_w)//stride + 1

img = np.pad(input_data, [(0,0), (0,0), (pad, pad), (pad, pad)], 'constant')
col = np.zeros((N, C, filter_h, filter_w, out_h, out_w))

for y in range(filter_h):
y_max = y + stride * out_h
for x in range(filter_w):
x_max = x + stride * out_w
col[:, :, y, x, :, :] = img[:, :, y:y_max:stride, x:x_max:stride]

col = col.transpose(0, 4, 5, 1, 2, 3) # (N, C, filter_h, filter_w, out_h, out_w) -> (N, filter_w, out_h, out_w, C, filter_h)

col = col.reshape(N * out_h * out_w, -1)
return col

 

・畳み込み層の使用

input_data = np.random.rand(2, 1, 4, 4)*100//1 # number, channel, height, widthを表す
print('========== input_data ===========\n', input_data)
filter_h = 3
filter_w = 3
stride = 1
pad = 0
col = im2col(input_data, filter_h=filter_h, filter_w=filter_w, stride=stride, pad=pad)
print('============= col ==============\n', col)

 

・出力

========== input_data ===========
[[[[77. 89. 22. 24.]
[51. 27. 81. 89.]
[87. 71. 64. 12.]
[12. 34. 17. 85.]]]

[[[20. 92. 53. 41.]
[66. 54. 6. 29.]
[ 3. 59. 64. 23.]
[18. 82. 92. 37.]]]]
============= col ==============
[[77. 89. 22. 51. 27. 81. 87. 71. 64.]
[89. 22. 24. 27. 81. 89. 71. 64. 12.]
[51. 27. 81. 87. 71. 64. 12. 34. 17.]
[27. 81. 89. 71. 64. 12. 34. 17. 85.]
[20. 92. 53. 66. 54. 6. 3. 59. 64.]
[92. 53. 41. 54. 6. 29. 59. 64. 23.]
[66. 54. 6. 3. 59. 64. 18. 82. 92.]
[54. 6. 29. 59. 64. 23. 82. 92. 37.]]

→入力 ※イメージ:4×4ピクセルの画像2枚の、赤の強さ(RGBのR)

→出力 ※イメージ:3×3のフィルタで入力を抜き出した結果。

 

★プーリング層★

・プーリング層の実装

def forward(self, x):
# FN: filter_number, C: channel, FH: filter_height, FW: filter_width
FN, C, FH, FW = self.W.shape
N, C, H, W = x.shape
# 出力値のheight, width
out_h = 1 + int((H + 2 * self.pad - FH) / self.stride)
out_w = 1 + int((W + 2 * self.pad - FW) / self.stride)

# xを行列に変換
col = im2col(x, FH, FW, self.stride, self.pad)
# フィルターをxに合わせた行列に変換
col_W = self.W.reshape(FN, -1).T

out = np.dot(col, col_W) + self.b
# 計算のために変えた形式を戻す
out = out.reshape(N, out_h, out_w, -1).transpose(0, 3, 1, 2)

self.x = x
self.col = col
self.col_W = col_W

return out

 

★CNN全体★

※PCの性能が低いのでデータを大幅に削減する。

# 処理に時間のかかる場合はデータを削減
x_train, d_train = x_train[:50], d_train[:50]
# x_train, d_train = x_train[:5000], d_train[:5000]

x_test, d_test = x_test[:10], d_test[:10]
x_test, d_test = x_test[:1000], d_test[:1000]

 

Section5:最新のCNN

【要点】

AlexNet:

 2012年の画像認識コンテストで優勝したモデル。
 サイズ4096の全結合層の出力にドロップアウトを使用して、過学習を防止している。ja.wikipedia.org

 

【考察】

GPUを用いて高速な学習を実現している。とのこと。

→このあたりになると、単なる個人PCでは難しいと思われる。

※本Sectionのみ、確認テスト、実装なし。

 

E資格の勉強③深層学習day1

目次

1 本投稿の目的

深層学習(day1)に関する学習のまとめ

2 Section1:入力層~中間層

入力層 → 中間層 → 出力層

【要点】

入力層:

 ニューラルネットワークが入力を受け取る部分。

 任意の数の変数(ノード)を受け取る。(x1,x2,・・xN)と表現。

中間層: 

 入力層→出力層の間にある層。

 ※入力層からの最初の出力は中間層(1層目)が受け取る。

 この時、各変数に個別に設定された重み(w1,w2・・wN)を掛けた合計値(+バイアス項もある)を入力とする。

 入力に対して活性化関数を実施した値を、次の層(中間層or出力層)に渡す。

 

【考察結果】

確認テスト1:各変数に動物分類の実例を入れてみよう。

入力層:

 x1,x2,・・xN → 身長(cm)、体重(g)、耳の長さ(mm)。

中間層の入力:

 上記に各重み(w)を掛けた値の合計(総入力)

 ※ポイント:重みは要素の重要度に依存する。重要度(高)の要素ほど重みが大きくなる。

 

確認テスト2:以下数式をPythonで書け。

 W =[W1,W2,W3,W4]

 X =[W1,W2,W3,W4]

 u = W1X1 + W2X2 + W3X3 + W4X4 + b ← この数式(行列の掛け算+b)

 (回答)

import numpy as np
u = np.dot(x, W) + b # np.dot(行列のドット積)

 

確認テスト3:中間層の出力を定義しているソースを抜き出せ。

 (回答)

# 2層の総入力
u2 = np.dot(z1, W2) + b2

# 2層の総出力
z2 = functions.relu(u2)

 

【実装演習】

演習ソース

# 重み
W = np.array([
[0.1, 0.2, 0.3],
[0.2, 0.3, 0.4],
[0.3, 0.4, 0.5],
[0.4, 0.5, 0.6]
])

print_vec("重み", W)

# バイアス項
b = np.array([0.1, 0.2, 0.3])
print_vec("バイアス", b)

# 入力値
x = np.array([1.0, 5.0, 2.0, -1.0])
print_vec("入力", x)

# 総入力
u = np.dot(x, W) + b
print_vec("総入力", u)

# 中間層出力
z = functions.sigmoid(u)
print_vec("中間層出力", z)

 

実行結果

*** 重み ***
[[0.1 0.2 0.3]
[0.2 0.3 0.4]
[0.3 0.4 0.5]
[0.4 0.5 0.6]]

*** バイアス ***
[0.1 0.2 0.3]

*** 入力 ***
[ 1. 5. 2. -1.]

*** 総入力 ***
[1.4 2.2 3. ]

*** 中間層出力 ***
[0.80218389 0.90024951 0.95257413
 

→ 総入力 =「入力」と「重み(W)」のドット積 + バイアス項

 中間層出力 = シグモイド関数(総入力)

 となっている事を確認できる。

 ※シグモイド関数:入力を「0~1の範囲」の数値に変換する関数。後述するのでここでは詳しく記述しない。

 

3 Section2:活性化関数

入力層中間層 出力層

【要点】

活性化関数:値を非線形に変換する関数。出力を次の層に渡す前に使用する。

Section1で行っていた「 W1X1 + W2X2 + W3X3 + W4X4 + b・・」は線形の処理。これを線形の出力に変換する事が目的。

 

中間層で利用する活性化関数。

・ステップ関数(現在はほぼ利用されていない)

 ある一定の点を境に、出力が変わる関数。(0 or 1)

シグモイド関数

 数式:f(u) = 1/ (1+ e^-w)

 値を0~1の範囲に変換する関数。ネイピア数を使用しており、微分が容易にできる。

・ReLU関数

 ある一定の点を境に、出力が変わる関数。

  ある一点を満たしていない = 0

  ある一点を満たす = 0~1の範囲

 

出力層で利用する活性化関数。※「出力層の活性化関数」を参照。

・ソフトマックス関数

・恒等写像

シグモイド関数

 

【考察結果】

確認テスト1:線形と非線形の違いを図に書いて簡易に説明せよ。

 

線形:直線としてグラフに表示できる。

f:id:you_it_blog:20211012233852p:plain

非線形:直線としてグラフに表示できない。※厳密には「線形が満たす条件を満たしていない」もの。

f:id:you_it_blog:20211012234114p:plain

※グラフの作成には以下を使用した。

www.geogebra.org

 

確認テスト2:配布されたソースコードの該当する箇所を抜き出せ。

※活性化関数の使用箇所

 (回答)

y = functions.sigmoid(u2)

 

【実装演習】

演習ソース

# 重み
W = np.array([
[0.1, 0.2, 0.3],
[0.2, 0.3, 0.4],
[0.3, 0.4, 0.5],
[0.4, 0.5, 0.6]
])

# バイアス項
b = np.array([0.1, 0.2, 0.3])

# 入力値
x = np.array([1.0, 5.0, 2.0, -1.0])

# 総入力
u = np.dot(x, W) + b
print_vec("総入力", u)

# 中間層出力
z = functions.sigmoid(u)
print_vec("中間層出力", z)

 

実行結果

*** 総入力 ***
[1.4 2.2 3. ]

*** 中間層出力 ***
[0.80218389 0.90024951 0.95257413

→「総入力」と「中間層出力」の違いに注目。

 シグモイド関数により、値の大小関係を維持したまま、値が0~1の範囲に変換されている。

 

4 Section3:出力層

入力層 → 中間層 出力層

【要点】

出力層:

 最終的なデータを出力する層。

 「中間層の出力 → 次の層の入力に使用するための値」であるが、

 「出力層の出力 → 人間が使用したい値」

 分類問題の場合は、該当の分類である確率であったり、

 回帰問題の場合は、想定される値(数値) となる。

誤差関数:

 出力層の出力と、正解(ラベル)の誤差を比較する関数。

 ※学習で使用した誤差関数は二乗和誤差。全ての誤差を2乗したものの総和 / 2

出力層の活性化関数:

 中間層の活性化関数とは異なる。(中間層とは出力する値の使い方が異なるため)

・恒等写像

 回帰問題の場合に使用する。値を何も加工しない。

 ※ 確率などでなく、値を知りたい(出力させたい)ため、加工する必要が無い。

 使用する誤差関数は2乗和誤差。

シグモイド関数

 分類問題(2クラス)の場合に使用する。値を0~1の範囲に変換する関数。

 使用する誤差関数はクロスエントロピー

・ソフトマックス関数

 分類問題(3クラス)の場合に使用する。値を0~1の範囲に変換する、かつ全確率の総和を1とする関数。

 使用する誤差関数はクロスエントロピー

 

【考察結果】

★誤差関数について★

確認テスト1:なぜ、引き算でなく2乗するか。また、「/2」はどういう意味を持つか。

 (回答:2乗する理由)

 符号の違いの考慮を無くすため。2乗すると、値は2乗されが、ラベルと出力の純粋な距離を取得できる。

 (回答:「/2」する理由)

 誤差から重みとバイアス項を修正する(誤差逆伝搬)のときに、微分を簡単にするため。本質的な意味はない。

 

★活性化関数について★

確認テスト1:ソフトマックス関数の数式に該当するソースコードを示し、1行ずつ処理の説明をせよ。

(ソフトマックス関数の数式)

f:id:you_it_blog:20211013110236p:plain

※数式取得元は以下。

ja.wikipedia.org

(回答 ※「★」=追加した説明コメント)

# ソフトマックス関数
def softmax(x):
# ★:ミニバッチの場合(概ね実装は同じ)
if x.ndim == 2:
x = x.T
x = x - np.max(x, axis=0)
y = np.exp(x) / np.sum(np.exp(x), axis=0)
return y.T

# ★:ミニバッチ以外の場合
x = x - np.max(x) # オーバーフロー対策
# ★:np.exp(x) → 数式の分母にあたる部分
# ★:np.sum(np.exp(x)) → 数式の分子にあたる部分
return np.exp(x) / np.sum(np.exp(x))

 

★誤差関数について★

確認テスト1:交差エントロピーの式に該当するソースコードを示し、1行ずつ処理の説明をせよ。

(回答 ※「★」=追加した説明コメント)

def cross_entropy_error(d, y):
if y.ndim == 1:
d = d.reshape(1, d.size)
y = y.reshape(1, y.size)

# 教師データがone-hot-vectorの場合、正解ラベルのインデックスに変換
if d.size == y.size:
d = d.argmax(axis=1)

batch_size = y.shape[0]
# ★:重要なのは「-np.sum(np.log(y[np.arange(batch_size), d] + 1e-7))
# ★:y:ラベル(正解:1、不正解:0) dnnの出力
# ★:1e-7:対数関数の答が「-∞」になることを防止するための値。
# ★:最終的に値を「-」することでlogの「-」を正数に変換する。
return -np.sum(np.log(y[np.arange(batch_size), d] + 1e-7)) / batch_size

 

【実装演習】

演習ソース:

誤差関数(2乗和誤差)の実装

# 平均二乗誤差
def mean_squared_error(d, y):
return np.mean(np.square(d - y)) / 2

誤差関数を使用

# 入力値
x = np.array([1., 2.])
network = init_network()
y, z1 = forward(network, x)
# 目標出力
d = np.array([2., 4.])
# 誤差
loss = functions.mean_squared_error(d, y)
## 表示
print_vec("出力", y)
print_vec("訓練データ", d)
print_vec("誤差", loss)

実行結果

*** 出力 ***
[1.02 2.29]

*** 訓練データ ***
[2. 4.]

*** 誤差 ***
0.9711249999999999

→yとdの誤差量が「誤差」として出力される。

 

5 Section4:勾配降下法

入力層 → 中間層 → 出力層

入力層中間層 ← 出力層 ※重みやバイアス項の修正に関係する。

【要点】

勾配降下法:

 深層学習※のそもそも目的 → 学習結果を通じて、重さ(W)やバイアス項(B)を「最も誤差が発生しない値 = 傾きが0になる値」に修正すること。

 ※深層学習 = 層が4層以上存在するNN。= 中間層が2層以上存在するNN。

 勾配降下法は、重さ(W)やバイアス項(B)を修正するための方法。

  

学習率: 

 誤差を反映させるときの割合。適切な値に設定する事が重要。

  →大きすぎる場合:振り子を強く振ったように、振り幅がどんどん大きくなる =発散してしまう。

  →小さすぎる場合:振り子を弱く振ったように、振り幅は小さい(最適解にゆっくり近づく。)が、ふり幅が弱いと、「誤差が小さいが最適解でない場所(=局所解)」から動けなくなる可能性がある。

 

勾配降下法の種類:

確率的勾配降下法(SGD):

 エポックごとに、学習データから一部をランダムに選んで学習する。

 確率的勾配降下法は、このような事が無い。また、オンライン学習(後述の確認テストを参照)も利用可能。

・バッチ勾配降下法:

 全データを一括学習 → 誤差を一気に修正する方法。

 ※データの追加時、全データを再度使用する必要がある。

・ミニバッチ勾配降下法:

 バッチ学習と確率的勾配降下法(SGD)の混合のような手法。

 データを一定単位のミニバッチにまとめる。

 ミニバッチ単位で学習を行い、全ミニバッチの誤差の平均を用いて誤差を修正する。

 → バッチ勾配降下法は「1命令1データ」 = 並列実行が不可能であるが、

  ミニバッチ勾配降下法は「1命令複数データ」 = 並列実行が可能。

 

【考察結果】

確認テスト1:オンライン学習とは何か。2行でまとめよ。

(回答)

 学習データの追加時に、都度パラメータを修正して、学習する方法。

 ※全データを一気に使用するバッチ学習では行えない。(毎回全データを使用することになり、現実的でない)

 

確認テスト2:勾配降下法の以下数式の意味を図に書いて説明せよ。

「W(t+1) = W(t) - ε∇Et」

 

(回答)

※Wに関する説明なので、バイアス項(B)についての説明は省略している。

―――――――――――――――――――――――――

エポック|  重み

―――――――――――――――――――――――――

t   |  Wt →→↓

    |      ↓ - ε∇Et (※誤差×学習率 = 改善)

t+1 |  Wt+1  ← ※前回のWに改善を行った値=次エポックのW

・   |  ・

t+n |  Wt+n

―――――――――――――――――――――――――

※考察

 この説明については「超AI入門講座」の「スタートテスト(一般)」で見た記憶がある。万一分からない場合、「超AI入門講座」にて復習する事にする。

 

 

6 Section5:誤差逆伝搬法

入力層 → 中間層 → 出力層

入力層中間層 ← 出力層 ※重みやバイアス項の修正に関係する。

【要点】

数値微分で更新量を求めると、入力層側ほど、更新量を求めるのが大変。

出力層側の同じ計算を何回も行うことになる・・。

 

誤差逆伝搬では、一度求めた更新量を再利用して、更新量を簡単に、高速に求める事ができる。(微分の連鎖率を使用する)

※この説明については「超AI入門講座」で分かりやすい解説がある。

連鎖率はプログラム関係ない数学の知識。以下が参考になる。

※このサイトは数学に関して何かとお勧めである。

manabitimes.jp

 

 

 

 

【考察結果】

確認テスト1:誤差逆伝搬法では不要な再帰処理を避けることができる。既に行った計算方法を保持しているソースコードを抽出せよ。

(回答 ※「★」=追加した説明コメント)

# 誤差逆伝播
def backward(x, d, z1, y):
print("\n##### 誤差逆伝播開始 #####")

grad = {}

W1, W2 = network['W1'], network['W2']
# 出力層でのデルタ
delta2 = functions.d_sigmoid_with_loss(d, y) ★ここ。「delta2」★
# b2の勾配
grad['b2'] = np.sum(delta2, axis=0)
# W2の勾配
grad['W2'] = np.dot(z1.T, delta2)
# 中間層でのデルタ
delta1 = np.dot(delta2, W2.T) * functions.d_relu(z1) ★「delta2」を流用★

→delta2を流用して、中間層の更新量の取得に使用している。

 これにより、計算量を「層の数-1」に抑えることができる。

 単純な数値微分では、計算量は「(層の数+1) × 層数/2」になる。

 ※いわゆるガウスの足し算。

mosipro.com

 

確認テスト2:2つの空欄に該当するソースコードを探せ

①∂E/∂y  ∂y/∂u

(回答)

delta2 = functions.d_mean_squared_error(d, y)

 

②∂E/∂y  ∂y/∂u  ∂u/∂w2ji

(回答)

# W2の勾配
grad['W2'] = np.dot(z1.T, delta2)

 

→上記は微分の連鎖例なので「/」に注意。割り算でない。「a/b」→「aをbで微分した物」という意味。あとは、重み(W)とバイアス項(B)の微分を行う際、偏微分を行っていることに注意。(分からないなら、「超AI入門講座」を再確認する)

 

 

E資格の勉強②機械学習レポート

目次

1 本投稿の目的

機械学習に関する学習のまとめ

2 線形回帰モデル

【概要】

教師データありの回帰手法(回帰問題を解くためのモデルの1つ)

入力:m次元のパラメータ

出力:入力の線形結合※予測値は^(ハット)をつける。

パラメータの誤差は最小二乗法で推定する。

 

【ハンズオン】

ボストンの住宅データセットから住宅価格の最適な査定を行ってみる。

######################
# 線形回帰
######################
# モジュールをインポート
from sklearn.datasets import load_boston
from pandas import DataFrame
import numpy as np
from sklearn.linear_model import LinearRegression # 線形回帰モジュール

# データセットインスタンス
dataset = load_boston()
# print(dataset) # {'data': array([[6.3200e-03, 1.8000e+01],・・

# データフレーム作成
df = DataFrame(data=dataset.data, columns=dataset.feature_names)
df["PRICE"] = np.array(dataset.target)

######################
# パターン①線形単回帰分析(説明変数が1)
######################
# 説明変数(部屋数)と目的変数を設定
data = df.loc[:, ["RM"]].values
target = df.loc[:, ["PRICE"]].values

# 線形回帰インスタンス生成
model = LinearRegression()
# model.get_params() パラメータの確認
model.fit(data, target) # パラメータの推定

# 未知のデータを予測(部屋数1の価格は?)
print(model.predict([[1]]))
# [-25.5685118] → 価格が負数(明らかにおかしい) → 部屋数1という学習データが無いため予測ができない(外挿)

# 未知のデータを予測(外挿でない「部屋数6」の価格は?)
print(model.predict([[6]]))
# [19.94203311] → 妥当かもしれない価格を取得できた。

######################
# パターン②線形重回帰分析(説明変数が複数)
######################
# 説明変数(犯罪率と部屋数)と目的変数を設定
data = df.loc[:, ["CRIM", "RM"]].values
target = df.loc[:, ["PRICE"]].values

# 線形回帰インスタンス生成
model = LinearRegression()
# model.get_params() パラメータの確認
model.fit(data, target) # パラメータの推定

# 未知のデータを予測1(犯罪率0.3で部屋数4の価格は?)
print(model.predict([[0.3, 4]]))
# 4.24007956
# 未知のデータを予測2(犯罪率0.3で部屋数5の価格は?)
print(model.predict([[0.3, 5]]))
# 12.6311478
# → 部屋数が1つ増えると価格は急激に上昇。部屋数の方が重要度が高い?と思われる。

【ハンズオン後の考察】

外挿問題について、今回は「価格が負数」という分かりやすい問題となっていたが、

分析データによっては、外挿問題が発生していることに気付かない可能性もあると思われる。学習結果について、以下のような方法で検証が必要と思われる。

 ・正常と不正な出力の基準を明確にして、不正な結果が出力されないか。

 ・実務担当者による判定結果と比較して、想定外の差異が無いか。

 

 

【関連記事】

後述のロジスティック回帰は教師データありの分類手法。
回帰と分類の違いは、以下URLが分かりやすかった。

aiacademy.jp

 

3 非線形回帰モデル

【概要】

線形でない現象に対する回帰手法

入力、出力、パラメータの誤差:線形回帰と同様

汎化性能を失う過学習に注意する必要がある。(線形回帰も注意が必要)
過学習の防止にはいくつか手法があるが、オーソドックスなものは正則化法(罰則法)

 ・L2ノルムを利用したRidge推定量でパラメータを0に近づける

 ・L1ノルムを利用したLasso推定量でパラメータを0にする

過学習が発生する場合、汎化性能を失う→学習データ以外の分析精度が低下する。

 

【ハンズオン】

非線形のデータを適切に予測できるモデルを作成する。

######################
# 非線形回帰
######################
# モジュールをインポート
import numpy as np
import matplotlib.pyplot as plt
from sklearn.kernel_ridge import KernelRidge


def true_func(x):
return 1 - 48 * x + 218 * x ** 2 - 315 * x ** 3 + 145 * x ** 4


# データ(散布)生成
n = 100
data = np.random.rand(n).astype(np.float32)
data = np.sort(data)
target = true_func(data) # 非線形のグラフを作成
# 散布にノイズを付与
target = target + 0.5 * np.random.randn(n)

# データ(散布)を描画
plt.scatter(data, target, color='blue', label='data')
plt.title('NonLinear Regression')

# 非線形回帰(カーネルリッジ回帰)インスタンスを生成
clf = KernelRidge(alpha=0.0002, kernel='rbf')
data = data.reshape(-1, 1) # 2次元1列の配列への変形
target = target.reshape(-1, 1) # 2次元1列の配列への変形
# 学習
clf.fit(data, target)
p_kridge = clf.predict(data)

# 学習結果を描画
plt.plot(data, p_kridge, color='red', linestyle='-', linewidth=3, markersize=6, label='kernel ridge')
plt.legend()

plt.savefig("test.png")

作成した画像ファイルは以下の通り。
(非線形の分布にフィットしたグラフを作成できている!)

f:id:you_it_blog:20211005233937p:plain

 

【関連記事】

非線形回帰の理解には以下サイトがとっかかりとして良かった。

www.gixo.jp

 

4 ロジスティック回帰モデル

【概要】

教師データありの分類手法(分類問題を解くためのモデルの1つ)

※名称に「回帰」とついているが、分類手法。紛らわしい・・。

入力:数値とm次元パラメータの線形結合をシグモイド関数※に入力

   ※入力値を0~1の範囲の数値に変換する関数の一つ。

    シグモイド関数は1/( 1+exp ^-ax)。

    「a」を使用する場合、aが1以下で小さいほど、緩やかな出力となる。

出力:0 or 1の2択に対して1となる確率。コインの裏表や、~する、しない等。

誤差関数には尤度関数を使用する。

 

【ハンズオン】

タイタニック号の乗客の生存状況を学習して、特定の条件[男性、30歳]にて生存できるか確認する。

######################
# ロジスティック回帰
######################
# モジュールをインポート
import numpy as np
from sklearn.datasets import fetch_openml
from sklearn.linear_model import LogisticRegression

# sklearnに付属している実験用データセットを読み込む
# データセットについての説明:https://www.openml.org/d/40945
titanic = fetch_openml(data_id=40945, as_frame=True)

# 必要な説明変数を取得(2列目:性別 、3列目:年齢)
x = titanic.data.to_numpy()[:, [2, 3]]
# 性別を数値に変換する。(male1,female0)
x[:, 0] = (x[:, 0] == 'male').astype(float)
x = x.astype(float)

# 欠損値が存在しない添え字の一覧を取得
# 一覧 = ~[反転](性別が欠損している索引の一覧 or 年齢が欠損している索引の一覧)
idx = ~(np.isnan(x[:, 0]) + np.isnan(x[:, 1]))
# 説明変数を絞り込み。(欠損値が存在しない索引に絞り込み)
x = x[idx]
# 目的変数を取得(欠損値が存在しない索引を取得)
y = titanic.target.to_numpy().astype(float)[idx]

# インスタンスを生成
model = LogisticRegression()
# 学習
model.fit(x, y)
# 未知のデータを判定。(男性、30)
print(model.predict([[1, 30]]))
# →[0.] = 生存できない

 

【関連記事】
使用したデータセットに関する説明。

説明変数と目的変数についての説明や、データの分布を確認できる。

www.openml.org

 

5 主成分分析

【概要】

複数の変数を1つに変換する。(次元の圧縮)

正しく利用することで、以下を実現する事ができる。

 ・使用する変数を減らして計算を簡単にする。

 ・(2~3次元に圧縮できる場合)データの可視化(=図への変換)が可能となる。

 

変換する際、線形変換後の値の分散が最大となる軸を探索する必要がある。

※線形変換後に全く値が散らばらない軸を使用すると、

 変換した値による分析が不可能となる。

 

探索はラグランジュ関数を微分して行う。

【用語】

寄与率:線形変換後の値が元々の情報と比較してどれほどの情報量を持っているか。

累積寄与率:各主成分の寄与率を大きい順に足し込んだ値。

 

【ハンズオン】

乳がん検査データ(32次元)を2次元に圧縮する。

また、圧縮したデータで適切に判定を実施できるか確認する。

######################
# 主成分分析
######################
# モジュールをインポート
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_breast_cancer
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt

# 乳がんデータセットを読み込む
cancer_ds = load_breast_cancer()

df_target = pd.DataFrame(cancer_ds.target, columns=["target"])
df_data = pd.DataFrame(cancer_ds.data, columns=cancer_ds.feature_names)
df = pd.concat([df_target, df_data], axis=1)

# 必要な説明変数を取得(備考:列番号でなく列名でも取得できる)
# dfから「全行」かつ「mean radius」列以降の列の情報を取得
# このデータセット1列目がtargetなので、上記の絞り込みで、目的変数を除いた全ての説明変数を取得できる。
x = df.loc[:, "mean radius":]
# 目的変数を取得(今回は欠損値が存在しない前提)
y = df.target

# データの標準化(データの大小を異なる項目間で比較できるようにする)
# ※主成分分析はデータの標準化を必ず実施する※
# https://free.kikagaku.ai/tutorial/basic_of_machine_learning/learn/machine_learning_unsupervised
x = StandardScaler().fit_transform(x)
# データを学習用とテスト用に分割する(train_test_split:デフォルトでは25%がテスト用、75%が学習用となる)
x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=0)

# 主成分分析のインスタンス生成
pca = PCA(n_components=2)
x_train_pca = pca.fit_transform(x_train)

# 主成分の寄与率は以下で確認可能。
# print(pca.explained_variance_ratio_)
# → [0.43711585 0.19513199]
# 第一成分で元データの43.3%、第二成分で元データの19.5%の情報を持っている。累積寄与率は62.8%

# 主成分分析した結果を図で確認してみる。
# 結果をデータフレーム化
df_pca = pd.DataFrame(x_train_pca, columns=["PC{}".format(x + 1) for x in range(2)])
# データフレームに解析結果も追加(主成分分析は教師なし学習であるが、今回は色分けするため追加)
df_pca['Outcome'] = y_train.values

# 目的変数ごとに色分けして描画するため、分割する。
malignant = df_pca[df_pca['Outcome'] == 0] # 悪性データ
benign = df_pca[df_pca['Outcome'] == 1] # 良性データ
# 描画
plt.scatter(x=malignant['PC1'], y=malignant['PC2'], label='malignant', c='r', marker='x', alpha=0.5)
plt.scatter(x=benign['PC1'], y=benign['PC2'], label='benign', c='b', marker='x', alpha=0.5)
plt.legend()
plt.xlabel('PC 1')
plt.ylabel('PC 2')
plt.savefig("aa.png")

描画結果は以下。概ね正しく分類できていると判断できる。
※かたよらずに混ざっている場合、分類が正しく実施できていないと判断する。

f:id:you_it_blog:20211009000447p:plain


さらに、主成分分析の結果を利用したクラスタリングを行う。
(主成分分析の目的はこれ。次元を減らして終わり・・ではない)
k平均法(k-means clustering)を使用する。

from sklearn.cluster import KMeans

# クラスター数は2(悪性、良性)
model = KMeans(n_clusters=2)
# クラスタリング
y_pred = model.fit_predict(x_train_pca)
# データフレームにクラスタリング結果を追加。
# 乳がんデータセットの目的変数は「0:悪性、1:良性」。KMeansの実行結果は「0:良性、1:悪性」なので、値を反転させた物を追加する。
df_pca['Outcome_pred'] = y_pred
df_pca['Outcome_pred'] = df_pca['Outcome_pred'].map({1: 0, 0: 1}).astype(int)

# 正解と学習結果を描画して目で確認する。
# ※主成分分析を用いてクラスタリングした結果と、正解データを描画する。今回は教師データが存在するため可能。
pred_kmeans_1 = df_pca[df_pca['Outcome_pred'] == 0]
pred_kmeans_2 = df_pca[df_pca['Outcome_pred'] == 1]
# 教師データを基にしたデータを描画(色付きの「×」を描画)
plt.scatter(x=malignant['PC1'], y=malignant['PC2'], label='malignant', c='r', marker='x')
plt.scatter(x=benign['PC1'], y=benign['PC2'], label='benign', c='b', marker='x')
# クラスタリングの結果を描画
plt.scatter(x=pred_kmeans_1['PC1'], y=pred_kmeans_1['PC2'], label='Ir1', c='b', alpha=0.5)
plt.scatter(x=pred_kmeans_2['PC1'], y=pred_kmeans_2['PC2'], label='Ir2', c='r', alpha=0.5)
plt.legend()
plt.xlabel('PC 1')
plt.ylabel('PC 2')
plt.savefig("aaa.png")

描画結果は以下。概ね正しく分類できているが・・境界付近に誤りがある。
※「□」と「×」の色が異なる部分が誤り。

ただ、一定の精度を保ったまま32次元 → 2次元まで圧縮できたため効果はある。

f:id:you_it_blog:20211009094859p:plain



【関連記事】

分かりやすい説明が記載されている。

一読すると、主成分分析をよく理解できた。

logics-of-blue.com

qiita.com

 

 

6 アルゴリズム_1(k近傍法-KNN)

【概要】

教師有り学習の分類手法。

識別対象データを受け取った際、識別対象データに最も近い(最近傍)のデータをk個取得。取得したk個のデータの分類を集計して、最も多い分類を返す。

例:k=3の場合

 ①識別対象データの最近傍を3個取得。

 ②「分類A:2個、分類B:1個」の場合 → 識別対象データの分類はAである、と判定する。

 ※「①」で取得するデータを、事前に学習させておく必要がある。

 

上記の通りなので、kの値が変われば結果が変わる。

kが増えるほど、取得する最近傍のデータが増えるため、識別結果は平均的になる。

言い換えるならば、kが増えるほど、識別範囲の境界線が滑らかな線になる。

 

【ハンズオン】

人口のデータ(と仮定したデータ)を分類する。
まず、学習データの作成。

######################
# k近傍法(KNN)
######################
# モジュールをインポート
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats


# 訓練データ生成処理(乱数なので、結果は毎回変わる)
def generate_data():
# 説明変数生成
x0 = np.random.normal(size=50).reshape(-1, 2) - 1 # 分類A
x1 = np.random.normal(size=50).reshape(-1, 2) + 1 # 分類B
# 作成した説明変数を結合
x = np.concatenate([x0, x1])
# 目的変数を生成して結合
y = np.concatenate([np.zeros(25), np.ones(25)]).astype(np.int)
return x, y


# 訓練データの作成 + 作成したデータの描画(確認のため)
x_train, y_train = generate_data()
plt.scatter(x_train[:, 0], x_train[:, 1], c=y_train)
plt.savefig("aa.png")

 

k近傍法に最適そうなデータを作成できた。

f:id:you_it_blog:20211009165234p:plain

次に、予測を行ってみる。(見やすくするため、判定の境界も描画する)
①numpyでの実装

# 距離を計算する関数(2乗するので符号の考慮が不要となる)
def distance(x1, x2):
return np.sum((x1 - x2) ** 2, axis=1)


# 予測処理
def knc_predict(x_train, y_train, X_test):
y_pred = np.empty(len(X_test), dtype=y_train.dtype)
for i, x in enumerate(X_test):
distances = distance(x, x_train)
nearest_index = distances.argsort()[:3] # 練習としてk=3を使用する。
mode, _ = stats.mode(y_train[nearest_index])
y_pred[i] = mode
return y_pred


# 結果を描画する関数
def plt_resut(x_train, y_train, y_pred):
xx0, xx1 = np.meshgrid(np.linspace(-5, 5, 100), np.linspace(-5, 5, 100))
# 散布図を描画
plt.scatter(x_train[:, 0], x_train[:, 1], c=y_train)
# 塗りつぶし2次元等高線図を描画。(判定の境界を確認できる)
plt.contourf(xx0, xx1, y_pred.reshape(100, 100).astype(dtype=np.float), alpha=0.2, levels=np.linspace(0, 1, 3))
plt.savefig("aaaa.png")


xx0, xx1 = np.meshgrid(np.linspace(-5, 5, 100), np.linspace(-5, 5, 100))
x_test = np.array([xx0, xx1]).reshape(2, -1).T

y_pred = knc_predict(x_train, y_train, x_test)
plt_resut(x_train, y_train, y_pred)

f:id:you_it_blog:20211009165540p:plain

 

②scikit-learnでの実装

from sklearn.neighbors import KNeighborsClassifier

xx0, xx1 = np.meshgrid(np.linspace(-5, 5, 100), np.linspace(-5, 5, 100))
xx = np.array([xx0, xx1]).reshape(2, -1).T
knc = KNeighborsClassifier(n_neighbors=3).fit(x_train, y_train) # 練習としてk=3を使用する。
plt_resut(x_train, y_train, knc.predict(xx))

f:id:you_it_blog:20211009170019p:plain

※結果に差異があるが、これはそもそもの教師データ(ランダム値)が実行の度に変わるため。教師データが同じであれば、結果も同じとなる。

 →scikit-learnの利便性が高いことを実感できる。

 

7 アルゴリズム_2(k平均法-K-mean)

【概要】

教師なし学習の分類手法。

受け取ったデータをk個のクラスタに分類する。

 

【処理の手順】

以下を、収束(= 結果が変化しなくなる)するまで繰り返す。

 ①各データからクラスタの中心となるデータを設定する。(初回はランダム)

 ②各データを最も距離の近いクラスタに分類する。

 ③分類したクラスタの平均ベクトル(中心)を計算する。

 ④クラスタの中心を更新して、再度①~③を行う。

 

【ハンズオン】

「主成分分析」で使用したため省略する。

 

8 SVM(サポートベクターマシン)

【概要】

2クラス分類問題の代表的な手法の1つ。

→回帰問題や教師なし学習でも応用されている。

※ここでは、線形分類をハンズオン対象とするが、

 カーネル関数と呼ばれる関数を用いることで、非線形の分類も可能。

 

【用語】

マージン最大化:

 分類問題なので、「k近傍法」に記載した図のように、分類の境界となる線が発生する。この線とデータの距離をマージンと呼び、マージンが大きいほど、適切な境界が設定できている。SVMでは、このマージンが最大となる境界を探す。この考え方をマージン最大化と呼ぶ。

ハードマージン:

 分類を完璧に識別できる境界が設定可能、という前提の分類。

ソフトマージン:

 分類を完璧に識別できない(誤差がある)、という前提の分類。

 ※現実としては、全ての情報を完璧に分類できる、という事はありえない。

 ソフトマージンにおける誤差を表す変数を「スラック変数」と呼び、

 誤差を最小化したうえで、マージンが最大となる境界を探す。

サポートベクトル:

 境界に最も近いデータのこと。SVMはマージンが最大となる境界を探すため、

 境界から離れているデータは、境界作成に全く影響しない。(あっても無くても結果に影響しない)

 境界に最も近いデータの = 境界の決定に使用されるデータをサポートベクトルと呼ぶ。

 

【ハンズオン】

アヤメの分類(2クラス分類)を行う。

######################
# SVM
######################
# モジュールをインポート
from sklearn import datasets, svm
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap

# データセットの読み込みhttps://scikit-learn.org/stable/datasets/toy_dataset.html#iris-dataset
iris = datasets.load_iris()

# 説明変数は最初の2つのみを取得(がく片の長さ、がく片の幅)
# ハンズオンのために結果を2次元の図で出力するため。
x = iris.data[:, :2]
# 目的変数の取得
y = iris.target

# 2:iris virginica」以外のインデックスを取得(データセット3クラス。実施する分類は2クラス分類のため)
idx = (iris.target != 2)
# 2:iris virginica」以外のデータのみに絞り込み
x = x[idx]
y = y[idx]

# SVMインスタンス生成
clf = svm.SVC(C=1.0, kernel='linear')
# データに最適化フィット
clf.fit(x, y)

# 背景色を利用して、分類と境界を描画する
# グラフの表示エリアの取得(説明変数の最大+1 と 最小-1の範囲とする)
x1_min = min(x[:, 0]) - 1
x1_max = max(x[:, 0]) + 1
x2_min = min(x[:, 1]) - 1
x2_max = max(x[:, 1]) + 1

# グリッド情報の作成。
# mgrid:格子状の配列を作成。500jなので、500×500の要素数となる、
xx, yy = np.mgrid[x1_min:x1_max:500j, x2_min:x2_max:500j]

# グリッド情報を並べなおす(np.c_:配列を結合する。ravel():配列を1次元に変換する)
xg = np.c_[xx.ravel(), yy.ravel()]

# 各グリッドの点の分類結果の予測をZに格納
z = clf.predict(xg)

# グリッド情報を並べなおす
z = z.reshape(xx.shape)

# 分類ごと塗りつぶしに使用する色の設定
cmap = ListedColormap([(0.5, 1, 1, 1), (1, 0.93, 0.5, 1)])

# 背景の色を表示
plt.pcolormesh(xx, yy, z == 0, cmap=cmap)

# 軸ラベルを設定
plt.xlabel('sepal length')
plt.ylabel('sepal width')

Xc0 = x[y == 0] # 目的変数;0のデータ
Xc1 = x[y == 1] # 目的変数;1のデータ

# 目的変数;0のデータを描画
plt.scatter(Xc0[:, 0], Xc0[:, 1], c='#E69F00', linewidths=0.5, edgecolors='black')
# 目的変数;1のデータを描画
plt.scatter(Xc1[:, 0], Xc1[:, 1], c='#56B4E9', linewidths=0.5, edgecolors='black')

# サポートベクトルを取得
SV = clf.support_vectors_

# サポートベクトルの点を赤枠で囲む(可視化のため)
plt.scatter(SV[:, 0], SV[:, 1], c='black', linewidths=1.0, edgecolors='red')

# 描画したグラフを表示
plt.savefig("ii.png")

f:id:you_it_blog:20211010102259p:plain

作成された境界と、境界の決定に使用されているサポートベクトルを確認できる。

 

 

 

E資格の勉強①応用数学レポート

目次

1 本投稿の目的

応用数学に関する学習のまとめ

2 線形代数(行列と固有値)

【行列】

行列の使い方として以下がある。(もちろん、その他の用途もある)

  • 大量の連立方程式をシンプルに表現する
    (行列の掛け算を理解すると、この意味が分かる。)

また、以下のような行列特有の専門用語があるので、覚える必要がある。

  • 単位行列(普通の数値における1。
    「X × 1 = X」と同様、掛け算しても結果を変えない行列で1と0で構成される。

さらに、行列の計算は手法を覚える必要がある。

  • 行列同士の足し算、引き算
    → 行列のサイズが同一であれば、単なる足し算、引き算で算出可能。
  • 行列同士の掛け算
    → 直行表のようなイメージで、全パターンの掛け算を加算していく。
     これは練習して確実に理解する必要がある。
  • 行列 → 通常の数値の変換
    → 左斜めに掛け算 - →右斜めに掛け算 がベースで、3×3ならたすき掛けが必要。

固有値

行列のn乗を簡単に求めるために必要となる。

※厳密には、固有値の一覧 = 対角行列と固有ベクトルを使用することで、

 行列の累乗を簡単に求める事ができるようになる。
 対角行列の累乗は各数値をn乗する、という簡単な方法で計算できるため。

 

行列に対して固有値分解(書籍により対角化とも記載されている)

を行うことで、累乗式に必要な以下を取得できる。

なお、正方行列でない場合は特異値分解、という手法で求める必要がある。


【補足:参考資料】

全体的に、以下の資料がとても参考になった。
★行列を知らない人のための線形代数学入門 - 広島大学

http://www.math.sci.hiroshima-u.ac.jp/m-mat/TEACH/senkei-daisuu.pdf

 

3 確率・統計

条件付確率が、特に注意が必要。

解説:

 ①PA(B) = P(B|A) = 事象Aが発生した世界で、事象Bが発生する確率※

 ②P(B∩A) = AとBが同時に発生する確率

 →①②は別の意味であるので注意。

※各順番が逆じゃない?と思うが、英語ベースで考えるとこの順番になる。
 (日本語と異なり、主語がとにかく先頭にくる形式)

その他、以下の用語がある。

  • 期待値(期待される値の平均)
  • 分散(実際の値と期待値の差を2乗したもの、2乗するのは±の考慮を無くすため)
  • 標準偏差(分散を√したもの。2乗 = 単位自体が変わるため、それを解消する)


【補足:参考資料】
条件付確率の参考

https://ousar.lib.okayama-u.ac.jp/files/public/6/60999/20201203115534771574/bgeou_175_027_037.pdf

 

ベイズ統計の考え方については、以下の本が参考になった。
※数時間読めば、図ベースで、条件付確率が理解できるようになる。

www.diamond.co.jp

 

4 情報理論

【自己情報量】

「-log(p(x))」という公式を始めてみたが、実際に問題を考えてみると意味が良く分かった。確率は0~1の範囲になるので、p(x)の値はほぼ分数になる。分数は累乗に直すと-n乗になるので答えが正数になる。かつ、値が小さければ小さいほど(-n乗のnが大きいほど)最終的な値(その情報の価値)が大きくなる。

【シャノンエントロピー

自己情報量の期待値。誤差関数の中身として使う、という事もできそう。

【カルバック・ライブラー・ダイバージェンス

想定していた確率分布と、実際の確率分布の違いを表すことができる。

ダイバージェンス <> 距離。

ダイバージェンスは距離と呼ぶには一部の定義を満たせていない。

ここでもΣは使用するので、Σは非常に重要。

【公差エントロピー

KLダイバージェンスの一部分。Qに対する情報をP(現実)の分布で平均する。

 

全て、公式を覚えておく(意味も理解する)はもちろん、自己情報量以外も実際に計算してみて、解いてみる必要があると思われる。


以上

E資格の勉強を始めてみる

目次

1 本投稿の目的

E資格の勉強を始めてみる。その経緯を記載する。

2 自分について
  • 資格は色々持っている(高度試験3つ、情報処理安全確保支援士試験合格)
  • 数学は高卒レベル。プログラム(Python)は1年ほど個人で経験あり。
3 学習を始めようとした理由

昨年、奇跡的にITストラテジストプロマネに合格できたので、次を考えていた。
そこで、自社の雰囲気を見てみると、AIの知識を求めいている雰囲気があった。
→AIについて何か資格を取っておけば、今後何か評価が上がるのでは?、と感じた。

4 学習方法(予定) 

以下オンリーで対策してみる。

ai999.careers


E資格の受験対象となる講座を色々確認してみたが、
最安でも5万円近くかかる。(165,000円 × 専門実践教育訓練にで70%戻る)

しかし、これなら、上手くいけば35,000円くらいで済む。[登録20,000円 + 月額3,000円×5カ月]

値段が安い分、自分で色々調べる必要があるみたいだが・・頑張ってみよう。

 

5 計画と目標

2021年9月1日:学習開始

~12月末:修了認定テストを通過。

2022年2月:試験を受験。できれば一度で合格したい・・。

 

6 その他

数学の知識が無いので、調べながら進める。

その過程で、役立つサイトなどがあれば忘備のため追記していく。

 

 

7 数学の資料

行列

www.mext.go.jp

 

条件付確率

https://ousar.lib.okayama-u.ac.jp/files/public/6/60999/20201203115534771574/bgeou_175_027_037.pdf

記号の解説:

 ①PA(B) = P(B|A) = 事象Aが発生した世界で、事象Bが発生する確率

 ②P(B∩A) = AとBが同時に発生する確率

 →①②は別の意味であるので注意。

区間和(更新無し)の最大値(abc183_d)

概要

区間和(更新無し)の最大値を求める方法を、図で解説する。
※加算、減算を同時に行える。

解説図

以下の様な区間の最大値を求める。

1.全探索(ダメなパターン)

処理量がO(nw)
→(問題の制約的に)最大で20万×20万・・・とても間に合わない。

2.累積和を使う

「要素が変わるタイミング」は以下の通り。

これを1つの配列(変動表)にまとめて・・

累積和を求める。

→最大値は「7」と分かる。
この方法なら処理量はO(n+w)。最大で20万+20万なので、問題なく回答できる。