就活生のブログ

就活中の理系大学生のブログです

ポートフォリオ作り ②

今回は、要件定義や使用言語とフレームワークの選定です。

 

 

【要件定義】

作ろうと思っているメディア系のWEBサービスに必要な機能は

・記事一覧表示機能

・記事詳細表示機能

・記事投稿機能

・管理ユーザ登録機能

・管理ユーザログイン機能

・画像ファイルのアップロード機能

・ページネーション機能

のため、記事情報やユーザ情報を保存できるデータベースと動的な機能が必要です。

 

【使用言語】

動的言語の候補としては開発者(情報)が多く、需要も高いPHPまたはRubyを使用することを考えています。それぞれのメリットとデメリットを調べました。

 

PHPのメリット

・開発者人口が多く、情報が豊富

・需要が高い(Word Press等でも使用)

フレームワークも充実

・学習コストが低い

 

PHPのデメリット

・暗黙の型変換を許容してしまうため、バグが内在しやすい

・上記と関連してチーム開発には向かない

 

Rubyのメリット

・日本語情報が豊富

・案件が多い

Ruby on Railsが便利

・スタートアップ界隈で人気

 

Rubyのデメリット

PHPよりも学習コストが高い

・世界的には人気が右肩下がり(将来的には日本も)

 

個人的に意外だったのがRubyの学習コストがPHPよりも高いらしいことです(逆だと思ってた)。

今までRubyは勉強したことがなかったため、今回採用しても良かったのですが、Rubyは今後衰退するであろうプログラミング言語5選に選ばれており、わざわざ学習するメリットが感じられませんでした。

 

というわけで、PHPを採用することにしました。

 

フレームワーク

PHPフレームワークは「ZendFramework」や「CakePHP」、「Laravel」が有名ですが、将来性はLaravelの一人勝ちらしいので、Laravelを使用したいと思います。

以下にLaravelのメリットを挙げておきます。

・コードが分かりやすい

・ライブラリが豊富

・簡単なアプリケーションを自動生成できる

・学習コストが低い

PHPフレームワークとして最も人気があり、情報も多い

 

今回はここまで。

ポートフォリオ作り ①

ポートフォリオを作るとき、どのサーバを利用するのか結構悩みました。どうしてそのサーバを選んだのか、忘れないようにメモっておきます。

結論から言うと、Herokuを採用しました。

 

【目次】

 

【サーバ選びで気にしたポイント】

サーバーの候補としては「Heroku」「AWS」「GCP」「VPS」があります。このとき、以下のポイントを気にしながらサーバーを選択しました。

 

・お金をかけたくない

・学習コストが低い

・管理が楽

・需要の高い技術を使いたい

 (ただ、AWSみたいに需要の高い技術は学習コストが高い)

 

各サーバーの特徴は以下のような感じです。

 

「Heroku」

メリット:インフラの知識が乏しい人でも簡単に使える

デメリット:拡張性が低くパフォーマンスも低い(無料プラン)

 

AWS

メリット:拡張性が高く採用している企業が多いため、技術として需要が高い

デメリット:課金形態が複雑でコスト管理が難しく、学習コストが高い

 

GCP

メリット:無料枠がかなり充実している

デメリット:リージョンが少ないので障害に弱い

 

VPS

メリット:コストが安い

デメリット:パフォーマンスが低く、管理コストが高い

  

一長一短ですが、とりあえずスピード感を持ってポートフォリオ を作成したいので学習コストが低いHerokuを使用することにしました。Herokuは無料プランまたは月額課金制なので、不正アクセスやサーバーへの攻撃に対しても「等しく課金」されるため、突然の高額請求を防ぐことができるのも魅力的でした(AWS高額請求の体験談とか読むとこわい)。

 

【Herokuの登録】

まず、Herokuのアカウント登録をしました。Heroku | 新規登録

 氏名、メールアドレス 、職業、国、主な開発言語について回答し、登録したメールアドレスに届いたリンクを踏んでパスワードを設定し、利用規約に同意すれば完了です(めっちゃ簡単)。

 

【Heroku CLIのインストール】

次に、Herokuをコマンドラインから操作できるツール(Heroku CLI)を用意しました。 Macの場合、ターミナルで以下のコマンドを入力するだけです。

brew tap heroku/brew && brew install heroku

 

【Herokuにログイン】

先ほど登録したHerokuのアカウントにログインします。

heroku login -i

 

【Herokuにデプロイ】

実際にHerokuにアプリケーションをデプロイします。適当なディレクトリを作ってその中で適当なアプリケーションをクローンします。

mkdir hoge
cd hoge
git clone 'https://github.com/heroku/java-getting-started.git'

 

次に、デプロイするために以下のディレクトリでデプロイ用のアプリケーションを作成します。

cd java-getting-started/
heroku create (アプリケーション名)

 

以下のような出力が出てきます。例)piyo-piyo-99999

Creating app... done, piyo-piyo-99999
https://piyo-piyo-99999.herokuapp.com/ | https://git.heroku.com/piyo-piyo-99999.git

 

最後に、デプロイします。

git push heroku main

 

https://piyo-piyo-99999.herokuapp.com/(ランダム値)にアクセスして以下のような画面が出れば成功です。

 

f:id:taka_hatene:20210315022715p:plain

 

もしURLが分からなくなったら以下のコマンドで確認できます。

 

heroku domains  

 

今日のところはここまで。お疲れさまでした。

 

【参考】

以下のサイトを参考にしました。感謝。

 

you88.space

tech-blog.rakus.co.jp

 

 

GitとGitHubの使い方

チームで開発を行うとき、バージョン管理の手段としてGitとGitHubは必ずと言っていいほど必要になってきます。今回はGitとGitHubの使い方を備忘録としてまとめて行きたいと思います。

 

【目次】

 

【Gitとは】

Gitとはバージョン管理を行うためのシステムです。

バージョン管理システムには、特定のリポジトリにファイルや履歴情報を集める「集中型」と個々人のマシンのリポジトリにファイルや履歴情報を集める「分散型」に大きく分けられますが、Gitは後者の分散型です。Gitはロールバックや修正履歴の整理が簡単で、エンジニアにとってなくてはならない存在です。

 

GitHubとは】

GitHubとはGitのリポジトリをまとめたソースコード管理サービスです。

GitHubソースコードホスティング(インターネット上のサーバにアップ)することで複数人の開発者と協働してコードを管理・編集することが出来ます。GitHubを利用する前にいくつか必要な知識があります。

 

リポジトリとは】

リポジトリとは管理するファイルや履歴情報を保管する領域です。

個々人のマシンのリポジトリを「ローカルリポジトリ」、チーム全体で使用するネットワーク先のサーバー上などにあるリポジトリを「リモートリポジトリ」と言います。

 

【インデックスとは】

インデックスとはコミットを行う前に変更内容を一時的に保管する領域です。

インデックスに追加されたファイルのみコミットすることができます。

 

【コマンド一覧】 

【アッド(add)】

アッドとはファイルの作成・変更・削除をインデックスに追加するコマンドです。

 

【コミット(commit)】

コミットとはファイルやディレクトリの追加・変更をローカルリポジトリに反映するコマンドです。

コミットはなるべく一つの作業ごとに行い、作業が複雑になりすぎないようにしましょう。

 

【フォーク(fork)】

フォークとはリポジトリをコピーするコマンドです。

他の開発者が作成したオリジナルのリポジトリを自分のアカウントにコピー(fork)してバグを修正し、その開発者にバグ修正に関する変更を提案することができます。

 

【クローン(clone)】

クローンとはリモートリポジトリをローカルリポジトリにダウンロードするコマンドです。

フォークはGitHubサーバー上でリポジトリの複製を行うコマンドであるのに対して、クローンはサーバー上のリポジトリをローカルPCに複製することができます。GitHub上のリポジトリをローカル上にコピーしたいときはフォーク(GitHubサーバーの自分のアカウントに複製)してからクローン(ローカルPCに複製)します。

 

【プルリクエスト(Pull request)】

プルリクエストとは自分の行った変更をリモートリポジトリに通知する操作です。

オリジナルリポジトリを直接編集できない場合、オリジナルリポジトリの管理者に対してフォークしたリポジトリを介して変更作業を通知することができます。

  

【ブランチ(branch)】

ブランチとは作業を分岐させて履歴の流れを記録するコマンドです。

作業を分岐することで同時に一つのソースコードやアプリケーションに対してバグ修正・機能追加ができます。基本的に開発する機能ごとにブランチを切ったり、修正と追加をブランチで切ったりします。

 

 

【フェッチ(fetch)】

フェッチとはリモートの「master」ブランチをローカルの「origin/master」ブランチに持ってくるコマンドです。

フェッチを取り消したいときは「git reset --hard HEAD」です。

 

【マージ(merge)】

マージとはローカルの「origin/master」ブランチをローカルの「master」ブランチに持ってくるコマンドです。

マージを取り消したいときは「git merge --abort」です。

 

【プル(pull)】

プルとはフェッチとマージを同時に行うコマンドです。つまり、リモートの「master」ブランチからローカルの「origin/master」ブランチを介してローカルの「master」ブランチに持ってくるコマンドです。

プルを取り消したいときは「git merge --abort → git reset --hard HEAD」です。

 

【プッシュ(push)】

プッシュとはファイルの追加や変更の履歴をリモートリポジトリにアップロードするコマンドです。

 

 

3月の予定

 【目次】

 

【当面の目的】

就活に利用できるオリジナルアプリを作成することが目的です。

UnityのML-Agentsを利用して3次元の画像入力から2次元の画像を作成するアプリを作成してみようと考えています。前回ネット上の素材を利用してゲームを作成したとき、収益化する為には著作権に配慮する必要があり、著作権に関する知識が乏しかったことから非常にハードルが高く感じました。著作権フリーな画像を自動作成するツールがあれば便利だなと思った為、作ってみようと考えています。

  

【今月の予定】 2021/3/1~31

・大学院入学手続き

・ 画像を学習 

ポートフォリオの環境作成

 

強化学習のサイクルを箇条書きしてみた

強化学習の勉強がてら大事だなーと思ったことを書き下してます。ご指摘・ご助言あれば幸いです。

 

強化学習とは試行錯誤を繰り返しながら環境(状態)に適応するようにエージェント(学習主体)が学習するものです。

強化学習は4つのステップを回すことで学習・実行しています。

 

 

① 状態の観察

 エージェントは環境を「観察」することで「状態」を取得します。

状態とは エージェントの行動によって変化する環境の要素のことです。 

 

ここで大事な点はいくつかあります。

 

・全ての状態を観察させようとすると学習に時間がかかりすぎるため、必要最低限の情報に留める必要があります。

 

離散値(数や量では測れない値)を扱うときは「one-hot表現」を使用する必要があります。

(例えば、大学生がどのように昼食を取るのか予測する時、学生の選択を「(昼食を)0:食べない、1:食堂で食べる、2:それ以外の場所で食べる」と分類した場合、「0:食べない」と「2:それ以外の場所で食べる」をそれぞれ半分の確率で選ぶ生徒を連続値として学習すると「1:食堂で食べる」に近づいてしまいます。このように値に関連がない場合、離散値に適したone-hot表現を使用する必要があります)

 

連続値を扱うときは「正規化」(あらかじめ指定した最大値と最小値の範囲におさまるように、データを整形)した方が学習効率が良いです。

 

・位置情報は絶対位置よりもエージェントとの相対位置で学習した方が「汎化性能」が向上します。

 

② 観察とポリシーを基に行動

 観察したあと、「状態」に応じてエージェントが持つ「ポリシー」に従って行動を決定します。

ポリシーとはエージェントが持つ考え方や傾向のことです。

 

ここで大事な点は以下です。

 

・学習コストを抑えるため、行動の分類はなるべく少なくします。

(例えば、左に「0:移動しない、1:移動する」と右に「0:移動しない、1:移動する」と分類するよりも、「0:移動しない、1:左に移動する、2:右に移動する」とまとめて分類してしまった方が学習コストは低くなります)

 

③ 行動の結果に対する報酬

 行動したあと、エージェントの行動の「結果」に対して「報酬」を与えます。

報酬の種類には行動に対してすぐに報酬が与えられる時報とエピソード開始から現在までの合計の報酬が与えられる累計報酬(遅延報酬)が存在します。

 

ここで大事な点はいくつかあります。

 

一般的に行動に対して「即時報酬」を与えるよりもエピソードの結果に対して「累計報酬」を与えた方が、良い学習につながります。言い換えれば、近視眼的な結果よりも将来的な結果を重視する方が良い学習につながります。

 

・多くの場合、「プラス報酬」の方が「マイナス報酬」よりもエージェントに良い学習をもたらします。過度に大きな「マイナス報酬」は「プラス報酬」につながる望ましい行動を回避させてしまう可能性があります。

 

メモ:UnityのML-Agentsでは報酬シグナルとして、以下の3つが存在します。

 

・環境の状態に対して与えられる外因性の報酬(Extrinsic)

・未知の状態を訪れることに対して与えられる好奇心の報酬(Curiosity)

・デモを模倣することに対して与えられる模倣の報酬(GAIL)

 

④ 報酬を基にポリシーを修正

 報酬が与えられたあと、  エージェントは報酬に応じてポリシーを再評価・修正します。

 

メモ:UnityのML-Agentsでは訓練設定ファイル(*.yaml)に学習用のハイパーパラメータ(機械学習において人間が調整する必要があるパラメータ)が記述されています。ハイパーパラメータの一部を紹介します。

 

・max_steps:学習するステップ数

 一般的に 5.0e5 ~ 1.0e7(問題の複雑さに比例して設定)

 

・time_horizon:エージェントが収集する経験(観察、行動、報酬)の数

 一般的に32 ~ 2048(報酬が得られるまでの平均時間に比例して設定)

 

・summary_freq:統計情報の取得頻度(単位はステップ数)

 TensorBoardのグラフのビン幅に相当

 

おまけ(学習上の問題とハイパーパラメータの関係)

起こりうる学習上の問題に対して、調整すべきハイパーパラメータ(UnityのML-Agentsのパラメータ名)をメモっておきます。

 

① 問題:学習量が足りない

  対処:学習量(max_steps)を増やす

 

② 問題: エージェントが問題を理解できない

  対処:ニューラルネットワークのサイズ(num_layers, hidden_units, vis_encode_type)を調整

 

③ 問題:エージェントが探索しすぎ・しなさすぎ

  対処1:エントロピー(beta(PPO), init_entcoef(SAC))を調整

  対処2:学習率(learning_rate, learning_rate_schedule)を調整

 

 

 

 

強化学習の環境作成

【目次】

【概要】

 物理法則(重力・慣性力など)を取り入れた環境下で、球(以下、Roller Agent)にどのタイミングでどの方向に力を加えたら目標地点(Target)に到着するか学習させました。

(※)Targetに到着したらランダムな地点に移動します。

f:id:taka_hatene:20210223145941p:plain


【学習環境の作成】

Roller Agent:「Create→3D Object→Sphere」から作成。

「Rigidbody」を追加(重力や慣性力などの物理法則を適用)

「Behavior Parameters」を追加(観察と行動の設定)

「Decision Requester」を追加(10ステップごとに行動を決定するよう設定)

「RollerAgent.cs(新規スクリプト)」を追加(詳細は後述)

Target:「Create→3D Object→Cube」から 作成。

Floor:「Create→3D Object→Plane」から作成。


項目 説明
観察 ・TargetのXYZ座標
・RollerAgentのXYZ座標
・RollerAgentのXZ速度
行動 ・RollerAgentにX方向に力を加える
・RollerAgentにZ方向に力を加える
報酬 ・RollerAgentがTargetに到着した報酬
・RollerAgentが落下した罰
・迷った(時間経過)罰


【RollerAgent.cs(新規スクリプト)】

観察・行動・学習するため、Roller Agentに追加するスクリプト(RollerAgent.cs)を作成する必要があります。

(※) 著作権の関係からコードを一部省略しています(1)。
RollerAgent.cs

using System.Collections.Generic;
using UnityEngine;
using Unity.MLAgents;
using Unity.MLAgents.Sensors;

// RollerAgent
public class RollerAgent : Agent
{
    // ~~~中略~~~ //

    // 行動実行時に呼ばれる
    public override void OnActionReceived(float[] vectorAction)
    {
        // RollerAgentに力を加える
        Vector3 controlSignal = Vector3.zero;
        controlSignal.x = vectorAction[0];
        controlSignal.z = vectorAction[1];
        rBody.AddForce(controlSignal * 10);

        // RollerAgentとTargetの距離
        float distanceToTarget = Vector3.Distance(
                                 this.transform.localPosition,
                                 target.localPosition);

        // RollerAgentがTargetの位置に到着した時
        if (distanceToTarget < 1.42f)
        {
            // ① 到着した時、正の報酬を与える
            AddReward(1.0f);
            rate.successCount();
            EndEpisode();
        }

        // RollerAgentが床から落下した時
        if (this.transform.localPosition.y < 0)
        {
            // ② 落下防止のため、落下した時に罰を与える
            AddReward(-0.1f);
            rate.failureCount();
            EndEpisode();
        }

        // RollerAgentが探索してる時
        // ③ 探索を急かすため、時間経過で罰を与える
        AddReward(-0.001f);
    }
}


【学習結果】

3パターンの報酬と罰を設定し、それぞれ500000ステップの学習を行い、エピソード毎の報酬とステップ(1ステップ=0.02秒)の関係を図1にまとめました。エピソードはエージェントがターゲットに到着(報酬)またはフロアから落下(罰)、落下も到着もせずに40秒経過(報酬なし)でエピソードは終了します。


f:id:taka_hatene:20210302183241p:plain

図1 学習中の報酬:横軸がステップ数、縦軸が報酬
橙色:パターン1水色:パターン2赤色:パターン3


学習から得られた最終的なポリシーをエージェントに与えて、エージェント9つの600秒間の到着回数と落下回数の合計を測定したところ、表1のようになりました。

(※) 慣性が働くために単純にTargetの方向に力を加えるだけではTargetに到着せず、落下する可能性があります。

表1 パターンごとの到着回数と落下回数

パターン 到着報酬 落下罰 時間経過罰 到着回数 落下回数 到着率(%)
パターン1 1.0 0 0 1177 601 66.1
パターン2 1.0 -0.5 0 1961 1161 62.8
パターン3 1.0 -0.5 -0.005 2049 1083 65.4

約5万ステップ(1000秒)学習した時点で報酬の期待値はほぼ収束していることが分かった。

また、個々のパターンより以下のことが読み取れる。

パターン1は表1の「到着の報酬(1.0)と到着率(66.1%)から与えれる報酬(0.661)」と図1の「報酬値(0.60~0.70)」が近い値である

パターン2は表1の「到着の報酬(1.0)と到着率(62.8%)から与えれる報酬(0.628)」と「落下の罰(-0.5)と落下率(37.2%)から与えられる罰(-0.186)」を合わせた「報酬値(0.442)」と図1の「報酬値(0.35~0.45)」が近い値である

パターン3は時間経過罰により、報酬値が大きく低下しており、0付近に収束している。到着の報酬(0.654)と落下の罰(-0.173)から得られる報酬値(0.481)が時間経過罰(-0.005/ステップ)によって0.0付近に収束していることから、平均して約100ステップに1回、つまり【2.0秒に1回】の頻度で1つのエージェントは到着または落下している。これは表1より計算される頻度【1.7秒に1回】と概ね一致する(600秒間に9つのエージェントが3132回(2049+1083)到着または落下:600×9/3132=1.72)。


パターン1:到着時に報酬を与え、罰を与えずに学習したモデル

youtu.be


パターン2:到着時に報酬を与え、落下時に罰を与えて学習したモデル

youtu.be


パターン3:到着時に報酬を与え、落下時の罰と時間経過(-0.005/ステップ)の罰を与えて学習したモデル

youtu.be


【まとめ】

 落下罰を与えた場合、時間あたりの到着回数が上昇すること、到着報酬と落下罰、時間経過罰を与えた場合、学習中のデータ(図1)から時間あたりの到着回数および落下回数(表1)を予測可能であることが分かった。

【参考文献】

(1)布留川 英一・佐藤 英一(2018)『Unityではじめる機械学習強化学習 Unity ML-Agents実践ゲームプログラミング』ボーンデジタル

人工知能とは

 近い将来、人工知能(AI)が我々の仕事の多くを奪うとされています。逆に、人工知能という技術を利用した新たな仕事(AIビジネスやデータ調査官など)が生まれるとも言われています。人工知能の可能性と限界を適切に知ることは、これからの時代を生きていく上で最低限の教養となるでしょう。

 

【目次】

 

人工知能

 人工知能(AI:Artificial Intelligence)とはコンピュータ(計算機)を用いて知的な情報処理(学習・推論・判断)を行う技術や人工的な知能のことです。人工知能の分野の一つとして機械学習が存在し、代表的な機械学習の手法として教師あり学習教師なし学習強化学習が存在します。

          

    f:id:taka_hatene:20210221195226p:plain

 

機械学習

 機械学習とは大量のデータを学習することで、予測や分類などを行う技術やアルゴリズムのことです。ルールベース人工知能(人間が考えたルールに従って予測や判断を行うAI)とは違い、機械学習はデータに潜む規則性や相互関係などを自動的に見つけ出し、その学習を基に予測や判断を行います。

 代表的な手法として教師あり学習教師なし学習強化学習があります。

 

教師あり学習

 教師あり学習とは正解ラベル付きのデータを使って学習させる手法です。例えば、事前に正解付きの手書きの数字(0~9)を学習させることで、正解を付けていない手書きの数字を正しく認識できるようになります。

 

メリット:効率的にデータから学習することができます。

デメリット:膨大なラベル付きデータを用意する必要があります(数千、数万のラベル付きデータを用意することは容易ではありません)。

 

教師なし学習

 教師なし学習とは正解ラベルが存在しないデータを使って学習させる手法です。例えば、犬の画像と猫の画像からそれぞれの特徴を自動的に見つけることで、犬の画像と猫の画像を正しく分類できるようになります。

 

メリット:膨大なラベル付きデータを用意する必要がありません。

デメリット:分類基準を予測できない為、分類が実用上役に立たない可能性があります(例えば、犬か猫で分類するのではなく、毛色や柄で画像を分類してしまう可能性があります)。

 

強化学習

 強化学習とはコンピュータが「環境」や「状態」に応じて、どのように「行動」すれば「報酬」が最も多く貰えるかを学習する手法です。例えば、ロボットに「歩けた距離」を報酬として与えることで路面の状態(環境)や姿勢(状態)に応じてどのように動けばより多くの距離を歩けるのか(より多くの報酬を得られるのか)、学習させることができます。

 

メリット1度の行動に対する評価が難しい問題について扱うことが出来ます(例えば、オセロでは一手で多くのマスを取ることよりも、角のマスを取ることに繋がる一手の方が望ましい場面があります。強化学習では、短期的な報酬ではなく長期的な報酬に向けて行動するように学習させることが出来ます)。

デメリット:評価方法に対して意図しない行動を学習してしまう可能性が挙げられます。

 

 次回は、実際に強化学習を使用した最も単純なアプリケーションを紹介する予定です。