yshr10ic’s Blog

備忘録

MacBook Pro Git設定手順

こんにちは、@yshr10icです。

MacBook ProでのGitの設定手順を備忘録として残していきます。

前提条件

  • PC:MacBook Pro(13-inch, 2020, Four Thunderbolt 3 ports
  • OS:macOS Catalina(バージョン:10.15.4)
  • Homebrew:2.2.17

Homebrewより、最新のGitのインストール

$ brew install git
$ git --version
git version 2.24.3 (Apple Git-128)

ユーザ名、メールアドレスの設定

$ git config --global user.name xxx
$ git config --global user.email "xxx@example.com"
$ git config --global -l
user.name xxx
user.email xxx@example.com

ディレクトリ、ファイルの設定

$ mkdir ~/.ssh
$ touch ~/.ssh/config
$ chmod 700 ~/.ssh
$ chmod 600 ~/.ssh/*

SSHのConfig設定

$ vi ~/.ssh/config

Host *
  StrictHostKeyChecking no
  UserKnownHostsFile=/dev/null
  ServerAliveInterval 15
  ServerAliveCountMax 30
  AddKeysToAgent yes
  UseKeychain yes
  IdentitiesOnly yes

global .gitignoreの設定

$ mkdir -p ~/.config/git
$ touch ~/.config/git/ignore
$ vi ~/.config/git/ignore

.DS_Store

GitHub SSH接続設定

GitHub用の秘密鍵、公開鍵を作成

$ ssh-keygen -t ed25519 -N "" -f ~/.ssh/github -C xxx@example.com
$ pbcopy < ~/.ssh/github.pub

https://github.com/settings/keysを開いて、New SSH Keyを押す。

f:id:yshr10ic:20200523142041p:plain

Titleに分かりやすい名前を設定し、Keyに先ほどコピーした公開鍵を貼り付ける。 Add SSH Keyを押す。

f:id:yshr10ic:20200523142049p:plain f:id:yshr10ic:20200523142056p:plain

設定の追記

$ vi ~/.ssh/config

Host github.com
  IdentityFile ~/.ssh/github
  User git

動作確認

$ ssh -T github.com
Warning: Permanently added 'github.com,13.114.40.48' (RSA) to the list of known hosts.
Hi yshr10ic! You've successfully authenticated, but GitHub does not provide shell access.

参考サイト

以下、参考にさせていただいたサイトです!

qiita.com

qiita.com

MacBook Pro 設定一覧

こんにちは、@yshr10icです。

先日、MacBook Proを購入しました。その際の記事はこちらをご覧ください。

yshr10ic.hatenablog.com

現在、絶賛環境構築中なので、備忘録のために設定やインストールしたアプリの一覧を残していきたいと思います!

更新履歴

  • 2020/05/25 KeyboardCleanToolを追加
  • 2020/05/27 Caps Lockキーの無効化設定を追加
  • 2020/05/29 Android StudioおよびXcodeを追加
  • 2020/06/01 HyperSwitchを追加
  • 2020/06/10 Scroll Reverserを追加
  • 2020/08/14 Amphetamine、RunCatを追加
  • 2020/08/22 BetterTouchToolを追加

システム環境設定

一般

f:id:yshr10ic:20200522213918p:plain

デスクトップとスクリーンセイバー

f:id:yshr10ic:20200522214106p:plain

Dock

Dockの表示をデフォルトで非表示にする。

f:id:yshr10ic:20200522214216p:plain

アクセシビリティ

アクセシビリティ>ポインタコントロールからスクロールの速さを速くする。個人的には、一番速くすると速すぎたので、一つ手前の速さに設定した。

f:id:yshr10ic:20200522215556p:plain

セキュリティとプライバシー

セキュリティとプライバシー>ファイアウォールからファイアウォールをオンにする。

f:id:yshr10ic:20200522220056p:plain f:id:yshr10ic:20200522220109p:plain

Bluetooth

f:id:yshr10ic:20200522220400p:plain

キーボード

キーボード>キーボードからキーボードの動きを最速にする。

f:id:yshr10ic:20200522220626p:plain

キーボード>キーボード>修飾キーからCaps Lockキーを無効化する。

f:id:yshr10ic:20200527224220p:plain

キーボード>ショートカットからフォーカス移動をTabキーでできるように設定する。

f:id:yshr10ic:20200522220634p:plain

キーボード>入力ソースからライブ変換をオフにする。

f:id:yshr10ic:20200522220639p:plain

トラックパッド

タップでクリックできるように設定。

f:id:yshr10ic:20200522221211p:plain

省エネルギー

ディスプレイをオフにする時間はデフォルトだと5分と短いので、少し長めにする。

f:id:yshr10ic:20200522221404p:plain

共有

コンピュータ名を変更。

f:id:yshr10ic:20200522221532p:plain

既存アプリ

Garage Band

要らないので削除。 このMacについて>ストレージ>管理...>音楽制作>GarageBandサウンドライブラリを削除

f:id:yshr10ic:20200522221912p:plain f:id:yshr10ic:20200522221918p:plain

Finder

f:id:yshr10ic:20200522222115p:plain f:id:yshr10ic:20200522222121p:plain f:id:yshr10ic:20200522222128p:plain

Finderを開いて、Command + Shift + ドットを押すと、隠しファイル・隠しフォルダの表示・非表示を変更できる。

f:id:yshr10ic:20200522222507p:plain

ターミナルを開いて、以下のコマンドを実行することで、.DS_Storeファイルの作成を抑制することができる。

defaults write com.apple.desktopservices DSDontWriteNetworkStores true
defaults write com.apple.desktopservices DSDontWriteUSBStores -bool true

スクリーンショット

スクリーンショットの保存先を変更する。

f:id:yshr10ic:20200522222855p:plain f:id:yshr10ic:20200522222904p:plain f:id:yshr10ic:20200522222913p:plain

ターミナルを開いて、以下のコマンドを実行することで、スクリーンショット時のファイル名を変更できる。デフォルトではスクリーンショット yyyy-MM-dd HH.mm.ss.pngだが、今回はss yyyy-MM-dd HH.mm.ss.pngに変更する。

defaults write com.apple.screencapture name ss

アプリ(一般)

Google Chrome

一番はじめに入れました。 ただMacでのChromeのデザイン?が個人的にはイマイチなので、もしかしたらSafari使うことになるかも・・・

Slack

最近は、会社以外でも、友達との連絡、オンラインサロン、Kaggleなどのコミュニティ用などで必須のツールですね。

slack.com

Alfred

ランチャーアプリ。

Alfred

Alfred

  • Running with Crayons Ltd
  • 仕事効率化
  • 無料
apps.apple.com

Spotlightの設定をオフにする。

f:id:yshr10ic:20200523114313p:plain

AppCleaner

Macアプリをアンインストールするためのアプリ。 不要なゴミファイルまできちんと削除してくれます。

freemacsoft.net

The Unarchiver

解凍アプリ。多くの圧縮ファイルを解凍できる。

The Unarchiver

The Unarchiver

  • MacPaw Inc.
  • ユーティリティ
  • 無料
apps.apple.com

Spectacle

画面分割アプリ。

www.spectacleapp.com

権限求められるので、設定する。

f:id:yshr10ic:20200523101515p:plain

Skitch

画像キャプチャ・描画・共有アプリです。 ブログ用に入れました。

apps.apple.com

KeyboardCleanTool

キーボードの掃除をするときなどに、キーボードの入力を一時的にオフにするアプリ。

folivora.ai

HyperSwitch

アプリをウィンドウ単位で切り替えてくれるアプリ。

bahoom.com

Scroll Reverser

トラックパッドとマウスのスクロール方向を個別に設定できるアプリ。

デフォルトでは、マウスを接続したときに、スクロール方向がWindowsとは逆向きになってしまう。

https://pilotmoon.com/scrollreverser/pilotmoon.com

Amphetamine

Macのスリープを制御するためのアプリ。

Amphetamine

Amphetamine

  • William Gustafson
  • ユーティリティ
  • 無料
apps.apple.com

RunCat

CPUの負荷状況を確認できるアプリ。

RunCat

RunCat

  • Takuto Nakamura
  • ユーティリティ
  • 無料
apps.apple.com

BetterTouchTool

トラックパッドやキーボード、Touchbarにアクションを割り当てるアプリ。

folivora.ai

アプリ(開発)

iTerm2

ターミナルソフト。

www.iterm2.com

デザインの変更。

f:id:yshr10ic:20200523101750p:plain

フォントサイズの変更。デフォルトだと小さすぎたので、少し大きくする。

f:id:yshr10ic:20200523101745p:plain

iTerm2をショットカットで表示/非表示を切り替えられるように設定。

f:id:yshr10ic:20200523114449p:plain

OpenTerminal-Lite

Finderからiterm2を直接開けるようになるアプリ。

github.com

デフォルトのターミナルを設定し、アクセス許可をする。

f:id:yshr10ic:20200523113042p:plain f:id:yshr10ic:20200523113045p:plain

Homebrew

パッケージマネージャ。

brew.sh

Homebrew Cask

GUIツールを管理するためのパッケージマネージャらしい。初めて知った。

github.com

以下のリンクに詳しく書かれている。

qiita.com

最近のmacだと標準で使えるのではないのでしょうか?

と書かれているのですが、自分の環境だとbrew caskを実行したところ最初にインストールが走りました。

f:id:yshr10ic:20200523105925p:plain

Git

ソースコードのバージョン管理ツール。

brew install git

Visual Studio CodeVSCode

最近の開発は、基本的にVSCodeですね。VSCode拡張機能に関しては別記事でまとめる予定です。

azure.microsoft.com

PyCharm

Pythonでの開発に特化したIDEですね。昔はVSCodeしか使っていなかったのですが、最近は、簡単なスクリプトファイルの編集はVSCodeで行って、Djangoなどを使うときにはPyCharmを使っています。PyCharmには有料版のプロフェッショナルと無料版のコミュニティがあるのですが、私はコミュニティを使っています。

www.jetbrains.com

Android Studio

Androidアプリの統合開発環境

developer.android.com

Xode

iOSアプリの統合開発環境

Xcode

Xcode

  • Apple
  • 開発ツール
  • 無料
apps.apple.com

参考サイト

以下、参考にさせていただいたサイトです!

qiita.com

まとめ

ひとまず設定したのは、以上です!今後もアップデートしていく予定です!

GitHub GraphQL API v4を試してみる

こんにちは、@yshr10icです。

GitHub GraphQL API v4をPythonで実行してみたので、実行したときのメモを残しておきます。

なお、こちらを参考にさせていただきました。

目次

  1. GitHubのアクセストークンの取得
  2. PythonでAPIの実行
  3. まとめ

GitHubのアクセストークンの取得

今回は、PythonからAPIを実行する際に、OAuth認証で認証をするため、OAuth用のトークンを取得します。

まず初めにGitHubを開き、右上のアイコンから「Settings」を選択します。

f:id:yshr10ic:20200329170907p:plain

次に設定画面のペインの中から「Developer settings」を選択します。

f:id:yshr10ic:20200329170824p:plain

開発者設定画面のペインの中から「Personal access tokens」を選択し、「Generate new tokens」を押します。

f:id:yshr10ic:20200329170830p:plain

ここで、GitHubのパスワードを要求された場合は、パスワードを入力しましょう。

f:id:yshr10ic:20200329170837p:plain

APIの権限設定をし、一番下にある「Generate token」を押します。

f:id:yshr10ic:20200329170847p:plain f:id:yshr10ic:20200329170853p:plain

トークンが発行されるので、そのトークンをメモしておきましょう。

f:id:yshr10ic:20200329170901p:plain

なお、このトークンは二度と表示することはできないので、必ずどこかにメモしておきましょう。(トークンを忘れてしまった場合は、削除してから新規発行しましょう。)

f:id:yshr10ic:20200329172206p:plain

これでトークンの取得は完了です!

PythonAPIの実行

まずはクエリを実行するひな形を作ります。

import requests
import json


TOKEN = 'YOUR ACCESS TOKEN'
ENDPOINT = 'https://api.github.com/graphql'


def get_query():
    query = {
        'query': """
        query{
            xxx
        }
        """
    }
    return query


def post(query):
    headers = {'Authorization': 'bearer ' + TOKEN}
    response = requests.post(ENDPOINT, json=query, headers=headers)

    if response.status_code != 200:
        print('Post fails: {}'.format(response))

    return response.json()


if __name__ == "__main__":
    query = get_query()
    response = post(query)
    print(json.dumps(response, indent=2))

TOKENに先ほど取得したアクセストークンを貼り付けます。 get_queryメソッドでクエリを発行し、postメソッドに引数として渡します。 以降は、このget_queryメソッドのみを修正して、GitHub GraphQL API v4を実行していきます。

ユーザ情報の取得

自分のアカウントの情報を取得してみます。viewerは現在の認証されているユーザの情報を取得します。

def get_query():
    query = {
        'query': """
        query{
            viewer {
                createdAt
                login
                name
                url
            }
        }
        """
    }
    return query

取得結果。GitHubのアカウント作成してから3年半しか経っていないんですね。。。

{
  "data": {
    "user": {
      "createdAt": "2016-10-13T08:00:51Z",
      "login": "yshr10ic",
      "name": "yshr10ic",
      "url": "https://github.com/yshr10ic"
    }
  }
}

リポジトリ情報の取得

最新のリポジトリの3件の情報の取得と、リポジトリ数の取得をしてみます。 repositoriesの中で、作成日時の降順に並び替えをし、最初の3件を取得するように指定しています。 nodesの中ではcreatedAtが作成日時を指しますが、orderByの中ではCREATED_AT作成日時を指すので、注意が必要です。

def get_query():
    query = {
        'query': """
        query{
            viewer {
                repositories(first: 3 orderBy: {field: CREATED_AT, direction: DESC}) {
                    nodes {
                        createdAt
                        isPrivate
                        name
                    }
                    totalCount
                }
            }
        }
        """
    }
    return query

取得結果。

{
  "data": {
    "viewer": {
      "repositories": {
        "nodes": [
          {
            "createdAt": "2020-03-12T13:20:34Z",
            "isPrivate": false,
            "name": "baby-steps"
          },
          {
            "createdAt": "2020-03-08T23:00:29Z",
            "isPrivate": false,
            "name": "portfolio"
          },
          {
            "createdAt": "2020-03-08T09:02:26Z",
            "isPrivate": true,
            "name": "books"
          }
        ],
        "totalCount": 34
      }
    }
  }
}

コミット数の取得

2020/03/20~2020/03/29のリポジトリ毎のコミット数を取得します。

def get_query():
    query = {
        'query': """
        query{
            viewer {
                contributionsCollection(from: "2020-03-20T00:00:00", to: "2020-03-30T00:00:00") {
                    totalCommitContributions
                    commitContributionsByRepository {
                        repository {
                            name
                        }
                        contributions
                        {
                            totalCount
                        }
                    }
                }
            }
        }
        """
    }
    return query

取得結果。

{
  "data": {
    "viewer": {
      "contributionsCollection": {
        "totalCommitContributions": 69,
        "commitContributionsByRepository": [
          {
            "repository": {
              "name": "books"
            },
            "contributions": {
              "totalCount": 67
            }
          },
          {
            "repository": {
              "name": "blog"
            },
            "contributions": {
              "totalCount": 2
            }
          }
        ]
      }
    }
  }
}

まとめ

今回は、PythonGitHub GraphQL API v4を実行してみました。 GraphQLを触るのが初めてだったので、クエリの書き方に苦戦してしまいましたが、比較的簡単に情報を取得することができました。 これを使って何か作ってみたいと思います。

また、GraphQLについては、以下の書籍で勉強しようか迷い中です。

初めてのGraphQL ―Webサービスを作って学ぶ新世代API

Jupyter Notebookでサーバ上にあるファイルを一括ダウンロードする

やりたいこと

  • Jupyter Notebookをリモートサーバ上(Linux)で起動している
  • リモートサーバにある実行したファイルとか、教師データとかを一括ダウンロードしたい
  • リモートサーバにSSH接続することなく、ダウンロードしたい
  • Jupyter Notebook上では、複数ファイルやフォルダをダウンロードすることができない

やり方

0.以下のMyFolderを一括ダウンロードしたい f:id:yshr10ic:20190307160012j:plain

1.Jupyter Notebookで一括ダウンロードしたいフォルダの配下にいき、新規でPythonノートブックを作成

f:id:yshr10ic:20190307160017p:plain

2.zipコマンドを実行

bashを実行しているだけなので、zipコマンドじゃなくても、tarコマンドでも問題ない

!zip -r 保存するファイル名 保存対象

f:id:yshr10ic:20190307160003j:plain

3.MyFolder配下にzip化されたファイルができるので、それをダウンロード f:id:yshr10ic:20190307160008j:plain

ABEJA主催のSIX 2019に参加してきました

SIX 2019

株式会社ABEJAが主催する社会実装に関するAIの最新事例、活用技術に関するカンファレンス、SIX 2019に参加してきました。 備忘録を兼ねて、僕が参加したセッションについてメモしていきます。(箇条書きレベルですみません・・・)

six.abejainc.com

f:id:yshr10ic:20190305225511j:plain
ABEJA SIX 2019

本記事について

SIX 2019は2 Daysカンファレンス(1日目がディベロッパー向け、2日目がビジネスマン向け)ですが、諸事情により1日目のみ参加しました。参加したセッションは以下です。

  • 技 特別講演(講演者:株式会社ABEJA 緒方 貴紀 氏)

  • 食事画像認識モデル開発プロジェクトでの10 5個の教訓(講演者:株式会社FiNC Technologies 南野 充則 氏)

  • アノテーションで精度の高い教師データを作成するために必要な仕組み(講演者:株式会社ABEJA 寺本 拓磨 氏)

  • 徹底討論 : AI導入・運用を加速せよ、40分一本勝負!(講演者:マスクド・アナライズ 氏、株式会社ABEJA 岡田 陽介 氏、Still Day One 合同会社 小島 英揮 氏)

SIX 2019に参加した理由

  • ABEJA Platformという言葉を聞いたことがあるが、ABEJAについてよく知らなかったので、これを機に知っておきたかった

  • 最近画像のアノテーションを実施する機会があったのですが、うまくいかないことも多く、アノテーションで有名な?ABEJAさんが、どのようなツールでどのようにアノテーションを実施しているのか知りたかった

  • 参加費無料だったから、行きやすかった・・・

  • マスクド・アナライズ氏ってどんな人なのかちょっと気になっていた・・・

技 特別講演(講演者:株式会社ABEJA 緒方 貴紀 氏)

  • ABEJAのサービスの紹介

    • ABEJA PLATFORM
    • ABEJA INSIGHT for Retail
    • ABEJA PLATFORM Annotation
  • ABEJAのサービスの振り返り

    • 各サービスが2018年度、どれだけ使用されたか
    • 各サービスでどのような機能を追加したか
  • ABEJAのこれから

    • ABEJA PLATFORM Accelerator(MLaaS)
      • ユーザが学習に必要な画像などをアップロードすると、あらかじめ用意されたモデルで学習できる。使用できるモデルは順次増えていく予定。

abejainc.com

食事画像認識モデル開発プロジェクトでの10 5個の教訓(講演者:株式会社FiNC Technologies 南野 充則 氏)

  • 研究開発の目的

    • 栄養素・カロリーを画像からできるだけ精緻に推定すること
  • 研究開発で行ったこと

    • カロリー推定のアプローチ方法検討
      • 画像から何を推定するのか(レシピ or 栄養素 or 食材)
    • データセットの作成
      • レシピ&カロリーデータベースの作成
      • 評価用食事データセットの作成 → FiNCオフィスにて2000のレシピのデータセットを作ったとのこと!
      • 食事レシピ認識モデル用データセットの作成
    • モデルの作成
      • 食事レシピ認識モデルの作成
  • 5つの教訓

    • プロジェクトはアジャイルで進めるべき
      • DLは精度の評価が難しい
      • 大部分はブラックボックス(一定の理論はあるけども・・・)
      • 特に使用したことのないモデルを使用する場合は見積もりが難しい
    • 評価方法の決定から始める
      • 目的が曖昧になる、人によって解釈が異なる
      • 無駄に時間を過ごしてしまう
    • オペレーションは自社で構築
      • モデルよりもデータセットが大事
      • 質を保てるオペレーション
      • オペレーション構築はPoCフェーズでする。構築完了後に、拡大していく(他社を使っても良い)
    • PDCAの速度を最速にする
      • モデル作成がゴールではない
      • モデル公開後の精度を上げていくプロセスまで設計することが大事
      • 一番コストがかかるのはデータの収集~アノテーション
    • DL/ML人材はソフトウェア人材から輩出させるべき
      • 前処理の対応力
      • 幅広い知識
      • ソフトウェアエンジニアがDLできるようなカリキュラム作成が大事
      • 非常に優秀なDLエンジニアの獲得と、サーバサイドエンジニアの底上げ

アノテーションで精度の高い教師データを作成するために必要な仕組み(講演者:株式会社ABEJA 寺本 拓磨 氏)

  • ABEJAが提供しているアノテーションサービス
    • Annotation Tool(β版)
    • 委託サービス
  • アノテーションの要件定義
    • 答えが重なるラベル(チャーハンとピラフの分類など)
      • アノテーターによって傾向がぶれる
    • 解決策
      • 詳細なルール決め
      • ラベルの間引き(迷ったら、Aにラベル付けするなど)
    • 熟練工データセット
      • 特徴
        • 画像から分かりにくい
        • 様々な種類の画像がある
        • 傷の程度などによるレベル分け
      • 解決策
        • 画像補正、前処理(モデル化)
        • 境界線定義
        • チェックフロー
  • アノテーターの分析
  • 学習済みモデルを使ったアプローチ
    • 事前推論
      • 事前推論モデルの精度が高いと、モデルを信頼しすぎてしまい、適当にやってしまう
      • デコイを混ぜておく
    • 自動領域抽出
    • 能動学習

徹底討論 : AI導入・運用を加速せよ、40分一本勝負!(講演者:マスクド・アナライズ 氏、株式会社ABEJA 岡田 陽介 氏、Still Day One 合同会社 小島 英揮 氏)

  • 有名AIベンチャーにAI開発を頼むときに、予算1億円は妥当か
    • NVIDIAGPUサーバで3,000万
    • データサイエンティスト、AIエンジニアで1,500万/年×2年で3,000万
  • DGWA(出川)サイクル
    • Do:まずは試してみる
    • Go for Broke:「当たって砕けろ」の試行錯誤を繰り返す
    • Warm Mind:周囲の理解や失敗を許容する暖かい環境づくり
    • Re"A"ction:社内で反応・反響を起こしつつ「ありがとう」を忘れない

所感

  • 画像認識、アノテーションを中心に講演を聞きましたが、どこでも悩むことは同じだと感じました。いかにアノテーションを効率的に正確に実施するか、は各社で試行錯誤しているのかと。
  • ABEJAさんのAnnotation Toolで事前推論や能動学習など(すでに実装されている?)の機能が非常に便利そうなので、案件があれば使ってみたいなと思いました。
  • どこの企業さんでもPoCから先に進めるのを苦労している印象でした。DL/MLはお金はかかるけど結果はやってみないと分からないという難しい分野ではあると思うので、そこをどうお客さんに説明していくかが重要だと感じました。

OpenAI Gym入門

最近、強化学習に興味を持って勉強しています。まず手始めにOpenAI GymのDocumentationを通じて、強化学習について学んでみました。

そもそもOpenAI Gymってなに?

あの有名なイーロン・マスクなどが出資する非営利団体「OpenAI」が提供する、強化学習用の検証プラットフォームです。

gym.openai.com

公式サイトには、Gymは強化学習アルゴリズムを開発したり、比較したりするツールキットだと記載されています。

強化学習って?

下記のサイト、本がおすすめです。

blog.brainpad.co.jp

qiita.com

www.amazon.co.jp

Installation

さっそくインストールしてみましょう! gymはpipコマンドでインストールすることができます。(一部の環境では、他にインストールすべきライブラリがあります。)

pip install gym

GitHubからクローンして、インストールすることもできます。

git clone https://github.com/openai/gym
cd gym
pip install -e .

Environments

まずは、簡単に強化学習を試してみます。 以下のコードは、CartPole(倒立振子)を制御するためのものです。

import gym
env = gym.make('CartPole-v0')
env.reset()
for _ in range(1000):
    env.render()
    env.step(env.action_space.sample())

上記のコードを実行すると下記のようになります。 CartPoleでは、倒立している振り子を倒さないように、黒いカートを左右に移動させて制御します。

f:id:yshr10ic:20190217195007g:plain
CartPole

OpenAI Gymでは、CartPole-v0の箇所をMountainCar-v0MsPacman-v0Hopper-v2などに変えると、様々な環境を試すことができます。 なお、環境によってはgym以外に必要なライブラリもありますが、実際に実行した際に表示されるエラーメッセージを見れば、必要なライブラリはすぐに判断することができます。 試しに、環境をHopper-v2に変えて実行してみたところ、下記のようなエラーメッセージが出力されました。エラーメッセージから、mujocoが足りないことが分かります。

Traceback (most recent call last):
  File "<Anaconda Path>\envs\dev\lib\site-packages\gym\envs\mujoco\mujoco_env.py", line 11, in <module>
    import mujoco_py
ModuleNotFoundError: No module named 'mujoco_py'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "hopper.py", line 2, in <module>
    env = gym.make('Hopper-v2')
  File "<Anaconda Path>\envs\dev\lib\site-packages\gym\envs\registration.py", line 167, in make
    return registry.make(id)
  File "<Anaconda Path>\envs\dev\lib\site-packages\gym\envs\registration.py", line 119, in make
    env = spec.make()
  File "<Anaconda Path>\envs\dev\lib\site-packages\gym\envs\registration.py", line 85, in make
    cls = load(self._entry_point)
  File "<Anaconda Path>\envs\dev\lib\site-packages\gym\envs\registration.py", line 14, in load
    result = entry_point.load(False)
  File "<Anaconda Path>\envs\dev\lib\site-packages\pkg_resources\__init__.py", line 2322, in load
    return self.resolve()
  File "<Anaconda Path>\envs\dev\lib\site-packages\pkg_resources\__init__.py", line 2328, in resolve
    module = __import__(self.module_name, fromlist=['__name__'], level=0)
  File "<Anaconda Path>\envs\dev\lib\site-packages\gym\envs\mujoco\__init__.py", line 1, in <module>
    from gym.envs.mujoco.mujoco_env import MujocoEnv
  File "<Anaconda Path>\envs\dev\lib\site-packages\gym\envs\mujoco\mujoco_env.py", line 13, in <module>
    raise error.DependencyNotInstalled("{}. (HINT: you need to install mujoco_py, and also perform the setup instructions here: https://github.com/openai/mujoco-py/.)".format(e))
gym.error.DependencyNotInstalled: No module named 'mujoco_py'. (HINT: you need to install mujoco_py, and also perform the setup instructions here: https://github.com/openai/mujoco-py/.)

Observations

Environmentのstep関数に、どのように行動するかが記述されています。 step関数は以下の4つを返します。

  • observation (object型):環境を観察するための環境特有のオブジェクト。例えば、カメラのピクセル情報、ロボットの関節の角度や速度、ボードゲームのボードの状態などです。
  • reward (float型):直前の行動によって獲得した報酬の総和。報酬の大きさは環境により異なりますが、目標は常に報酬の総和を増加させることです。
  • done (boolean型):環境をリセットするかどうかを判断する変数。ほとんどのタスクは明確に定義されたエピソードに分割され、エピソード終了時にdoneがTrueとなります。
  • info (dict型):デバッグに役立つ情報。

タイムスタンプごとに、エージェントは行動(action)を選択し、環境(environment)は状態(observation)と報酬(reward)を返します。

f:id:yshr10ic:20190218201655j:plain

import gym
env = gym.make('CartPole-v0')
# エピソードを20回繰り返します
for i_episode in range(20):
    # エピソードの最初に実行され、状態を初期化します
    observation = env.reset()
    # 最大100回行動します
    for t in range(100):
        # 画面に現在の状態をレンダリングします
        env.render()
        print(observation)
        # ランダムに行動
        action = env.action_space.sample()
        observation, reward, done, info = env.step(action)
        if done:
            print("Episode finished after {} timesteps".format(t+1))
            break

上記のコードを実行すると下記のようになります。

f:id:yshr10ic:20190219214254g:plain
レンダリング動画

[-0.02557018  0.00245127  0.02048424 -0.01868486]
[-0.02552116 -0.19295837  0.02011055  0.28039005]
[-0.02938032  0.00187102  0.02571835 -0.00588284]
[-0.0293429   0.19661487  0.02560069 -0.29034166]
[-0.02541061  0.00113741  0.01979386  0.01030424]
[-0.02538786  0.19596998  0.01999994 -0.27606835]
[-0.02146846  0.39080096  0.01447858 -0.56237679]
[-0.01365244  0.58571678  0.00323104 -0.85046331]
[-0.0019381   0.78079452 -0.01377823 -1.14212848]
[ 0.01367779  0.9760938  -0.0366208  -1.43910026]
[ 0.03319966  1.17164732 -0.0654028  -1.74299798]
[ 0.05663261  1.36744966 -0.10026276 -2.05528828]
[ 0.0839816   1.1734857  -0.14136853 -1.79523137]
[ 0.10745132  0.98020202 -0.17727315 -1.54962217]
[ 0.12705536  1.17695256 -0.2082656  -1.8919686 ]
Episode finished after 15 timesteps
[-0.03312327  0.01541595 -0.02496491  0.02577558]
[-0.03281495 -0.17933925 -0.0244494   0.31047843]
[-0.03640174 -0.37410449 -0.01823983  0.59535156]
[-0.04388383 -0.56896647 -0.0063328   0.8822337 ]

Spaces

すべての環境には、行動空間と状態空間があります。 これらはSpace型で定義されます。

import gym
env = gym.make('CartPole-v0')
print(env.action_space)
#> Discrete(2)
print(env.observation_space)
#> Box(4,)

CartPole-v0では、行動空間はDiscrete(2)、状態空間はBox(4,)となっています。 Discrete(x)型は、非負の離散空間で0~x-1の範囲の値を取ります。 Box(n)型は、n次元の配列を表します。Boxの最大値・最小値は以下で確認できます。

print(env.observation_space.high)
#> [4.8000002e+00 3.4028235e+38 4.1887903e-01 3.4028235e+38]
print(env.observation_space.low)
#> [-4.8000002e+00 -3.4028235e+38 -4.1887903e-01 -3.4028235e+38]

Discrete型とBox型はもっとも一般的なSpaceです。 Spaceからサンプリングしたり、Spaceに属しているかを確認することができます。

from gym import spaces
space = spaces.Discrete(8)
x = space.sample()
print(space.contains(x))
#> True
print(space.n)
#> 8

Available Environments

Gymには、様々な環境が用意されています。

  • Classic control and toy text:大部分が強化学習の論文から引用された小規模なタスクです。
  • Algorithmic:複数の桁の足し算や文字列の順序の逆転などの計算をするタスクです。こうした計算はコンピュータは得意ですが、強化学習ではこれらを例題からアルゴリズムを学習します。これらのタスクは、シーケンスの長さを変えることによって難易度を変えることができます。
  • Atari:アタリのゲーム。
  • 2D and 3D robots:ロボットのシミュレーションを制御します。これらのタスクでは、高速で正確なロボットシミュレーション用に設計されたMuJoCoのエンジンを使用します。

The registry

Gymの目的は、共通のインターフェースを公開し、比較ができるようにバージョン管理された多くの環境を提供することです。 利用可能な環境のリストは、gym.env.registryで確認できます。

from gym import envs
print(envs.registry.all())
#> dict_values([EnvSpec(Copy-v0), EnvSpec(RepeatCopy-v0), EnvSpec(ReversedAddition-v0), ..., EnvSpec(MemorizeDigits-v0)])

出力結果が多すぎたので省略しましたが、私の環境では、2019年2月20日現在、797の環境が提供されていました!

おわりに

いかがだったでしょうか? まずはOpenAI Gymでどのような環境があり、どのように実装されているのかを確認すれば、強化学習の勉強を進めやすくなると思います!実際にstep関数がどのように実装されているか、GitHubで確認してみたいですね。

TensorFlowを使用したCNNの実装

前回の記事では、TensorFlowを使用して、MNISTを解くニューラルネットワーク(Neural Network:NN)を実装をしました。

yshr10ic.hatenablog.com

今回は、畳み込みニューラルネットワーク(Convolutional Neural Network:CNN)を用いて、MNISTを解いていきたいと思います。

CNNの具体的な説明に関しては、こちらの記事が非常に分かりやすかったです。

qiita.com

TensorFlowでの実装

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data

mnist = input_data.read_data_sets('MNIST_data', one_hot=True)

# input data/output data
X = tf.placeholder(tf.float32, [None, 784])
y = tf.placeholder(tf.float32, [None, 10])

# input image
# バッチサイズ、高さ、横幅、チャネル数
img = tf.reshape(X, [-1, 28, 28, 1])

# convolution layer 1
with tf.name_scope('conv1'):
    # フィルタの縦、横、チャネル数、フィルタの枚数
    conv1_f = tf.Variable(tf.truncated_normal([5, 5, 1, 32], stddev=0.1))
    # strides: バッチ方向、縦方向、横方向、チャネル方向にどれだけ移動させるか
    conv1_c = tf.nn.conv2d(img, conv1_f, strides=[1, 1, 1, 1], padding='SAME')
    conv1_b = tf.Variable(tf.constant(0.1, shape=[32]))
    conv1_o = tf.nn.relu(conv1_c + conv1_b)

# pool layer 1
with tf.name_scope('pool1'):
    # ksize: バッチ方向、縦方向、横方向、チャネル方向のどれだけの大きさでプーリングするか
    pool1_o = tf.nn.max_pool(conv1_o, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')

# convolution layer 2
with tf.name_scope('conv2'):
    conv2_f = tf.Variable(tf.truncated_normal([5, 5, 32, 64], stddev=0.1))
    conv2_c = tf.nn.conv2d(pool1_o, conv2_f, strides=[1, 1, 1, 1], padding='SAME')
    conv2_b = tf.Variable(tf.constant(0.1, shape=[64]))
    conv2_o = tf.nn.relu(conv2_c + conv2_b)

# pool layer 2
with tf.name_scope('pool2'):
    # ksize: バッチ方向、縦方向、横方向、チャネル方向のどれだけの大きさでプーリングするか
    pool2_o = tf.nn.max_pool(conv2_o, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')

# flatten layer
with tf.name_scope('flatten'):
    flatten_o = tf.reshape(pool2_o, [-1, 7 * 7 * 64])

# fully connected layer
with tf.name_scope('fully_connected'):
    fully_connected_w = tf.Variable(tf.truncated_normal([7 * 7 * 64, 1024], stddev=0.1))
    fully_connected_b = tf.Variable(tf.constant(0.1, shape=[1024]))
    fully_connected_o = tf.nn.relu(tf.matmul(flatten_o, fully_connected_w) + fully_connected_b)

# output layer
with tf.name_scope('output'):
    output_w = tf.Variable(tf.truncated_normal([1024, 10], stddev=0.1))
    output_b = tf.Variable(tf.constant(0.1, shape=[10]))
    output_o = tf.nn.softmax(tf.matmul(fully_connected_o, output_w) + output_b)

# loss function(cross entropy)
with tf.name_scope('loss'):
    loss = tf.reduce_mean(-tf.reduce_sum(y * tf.log(output_o + 1e-5), axis=[1]))

# training
with tf.name_scope('train'):
    train_step = tf.train.GradientDescentOptimizer(learning_rate=0.01).minimize(loss)

# evaluation
with tf.name_scope('accuracy'):
    correct = tf.equal(tf.argmax(output_o, 1), tf.argmax(y, 1))
    accuracy = tf.reduce_mean(tf.cast(correct, tf.float32))

# init
init = tf.global_variables_initializer()
saver = tf.train.Saver()

with tf.Session() as sess:
    sess.run(init)

    # test data
    test_images = mnist.test.images
    test_labels = mnist.test.labels

    for i in range(1000):
        train_images, train_labels = mnist.train.next_batch(50)
        sess.run(train_step, feed_dict={X: train_images, y: train_labels})

        if (i + 1) % 100 == 0:
            accuracy_val = sess.run(accuracy, feed_dict={X: test_images, y: test_labels})
            print('Step %4d: accuracy = %.2f' % (i + 1, accuracy_val))

    saver.save(sess, 'models/mnist_cnn_model', write_meta_graph=False)

前回のNNの実装では、accuracyは0.90前後でしたが、今回のCNNでは0.96前後まで上がっています! ただし、層を増やしている分、計算量も増えてしまっています。

今後に向けて

TensorFlowを用いてCNNを実装しました。 今後やっていきたいことは↓です。

  • パディングやストライドを変えたときの精度の変化を確認する

  • kerasを用いてCNNを実装する