macOSにPython環境を構築する（Python＋Pipenv）


# macOSにPython環境を構築する（Python＋Pipenv）

macOSにPythonの開発環境を再構築したので、手順を共有します。

構成を「pyenv＋Anaconda」から、「Python＋Pipenv」に乗り換えました。`pip freeze`と`pipdeptree`で情報を書き出しておいてから、旧環境を[維持管理手順](https://qiita.com/tanuk1647/items/c73aeb0d308dce800750)に従い削除。その後、必要な手順を実施していきました。

以下に、環境構築手順をまとめます。まっさらの状態から環境を構築する前提で書いていますので、そういった方のお役にも立つと思います。

## 要件

- 開発用のPythonは、システムにプリインストールされているPythonと分けてインストールすること
- サンドボックス化された、複数の環境を持てるようにすること


## 構成

- macOS High Sierra
- Python（Python3）
- Pipenv
- TensorFlow / Keras


## 変更履歴

- 2018/08/16
    - 初版作成


## 概要

以下手順で環境構築します。

1. Bash設定ファイルの整備
1. Xcode、Command Line Toolsのインストール
1. Homebrewのインストール
1. Pythonのインストール
1. Pipenvのインストール
1. ワークスペースの作成
1. 仮想環境の作成
1. Jupyter Notebookの設定
1. PDFの設定
1. GNU Core Utilitiesのインストール
1. 動作確認


## 注意事項

**注意事項**

- コマンド内に`<ワークスペース>`等の記載がある場合、各自の環境に合わせて読み替えて実行してください。冗長となるので、特に見落としそうな箇所を除けば、但し書きを書いていません。

```bash
$ cd <ワークスペース>
$ mkdir <プロジェクト>
$ cd <プロジェクト>
$ python -V
$ pipenv install
$ python -V
$ pipenv shell
$ python -V
$ exit
$ python -V
```

- コマンドは、一行ずつ実行してください。
- 何かをインストール、設定したはずなのに、`-bash: hoge: command not found`と言って怒られるときは、コマンド`exec $SHELL -l`で、シェルを再起動させると、解決することがあります。


**参考サイト**

- [シェルを再起動させる簡単な方法](https://qiita.com/yusabana/items/c4de582c6f85a42817d8)


## 謝辞

環境構築、および、本稿の作成にあたっては、参考サイトに記載のサイトのほかにも、多くのサイトを参考にさせて頂きました。心より御礼申し上げます。

## 手順1. Bash設定ファイルの整備

**目的**

- Bash設定ファイルを作成し、メンテナンスしやすい状態にする

**やること**

- Bash設定ファイルの作成
- Bash設定ファイルの編集

**手順**

- ターミナルを起動し、以下コマンドを実行する。

```bash
$ touch ~/.bash_profile
$ touch ~/.bashrc
```

- Finderでホームに移動し、`[command] + [shift] + [.]`で、隠しファイルを表示する。
- `.bash_profile`をエディタ（テキストエディット等）で開き、`.bashrc`を呼び出すよう冒頭に記載する。

```bash
test -r ~/.bashrc && . ~/.bashrc
```

**補足**

- 少し単純化して補足説明します。macOSでは、ターミナル起動時にログインシェルが実行され、ホームディレクトリ内の`.bash_profile`が読み込まれます。ターミナル上でコマンド`bash`を実行すると、非ログインシェルが実行され、ホームディレクトリ内の`.bashrc`が読み込まれます。このとき、環境変数は実行元から実行先へと引き継がれます。エイリアス等は引き継がれません。

- 以上をふまえると、以下とするのがスマートだと考えられます。
    - 環境変数は、`.bash_profile`のみに記載する
    - エイリアスの定義、シェル関数の定義、コマンドライン補完の設定は、`.bashrc`のみに記載する
    - `.bash_profile`から`.bashrc`を読み込むように記載する

**参考サイト**

- [Basics of OSX .bashrc v .profile v .bash_profile](https://www.anintegratedworld.com/basics-of-osx-bashrc-v-profile-v-bash_profile/)
- [本当に正しい .bashrc と .bash_profile の使ひ分け](https://qiita.com/magicant/items/d3bb7ea1192e63fba850)


## 手順2. Xcode、Command Line Toolsのインストール

**目的**

- macOS上でビルドできるようにする

**やること**

- Xcodeのインストール
- Command Line Toolsのインストール

**手順**

- App StoreからXcodeをインストールする。
- ターミナルを起動し、コマンド`sudo xcodebuild -license`を実行する。
- コマンド`xcode-select --install`を実行すると、ダイアログが出るので、インストールを選択する。


## 手順3. Homebrewのインストール

**目的**

- macOSにソフトウェアを簡単にインストールできるようにする
- 必要なソフトウェアをあらかじめインストールする

**やること**

- Homebrewのインストール
- OpenSSL、Pandocのインストール

**手順**

- ターミナルを起動し、[Homebrewの公式サイト](https://brew.sh/index_ja)に記載のコマンド（スクリプト）を実行する。
- ターミナルを起動し、Homebrewを使って、OpenSSL、Pandocをインストールする。なお、既にインストール済みの場合は、そう表示される。

```bash
$ brew update
Already up-to-date.

$ brew install openssl
Error: openssl 1.0.2o_2 is already installed
To upgrade to 1.0.2p, run `brew upgrade openssl`

$ brew install pandoc
Warning: pandoc 2.2.3.2 is already installed and up-to-date
To reinstall 2.2.3.2, run `brew reinstall pandoc`
```

**補足**

- OpenSSLはパッケージPycURLの、PandocはJupyter NotebookのPDFダウンロードに必要です。それらを利用する予定がない場合は、手順をスキップして頂いて構いません。


## 手順4. Pythonのインストール

**はじめに**

- 本手順では、Homebrewではなく、公式サイトのインストーラでPythonをインストールします。理由は、Homebrewで新規にPythonをインストールすると、問答無用で最新のPythonがインストールされてしまうためです。対応していないパッケージも少数ながら存在するにも関わらず、です。
- [テクニカルな手順](https://qiita.com/cokaholic/items/6db92c23b43d18bdab82)を応用することにより、過去版のPythonと、対応するpipenvをインストールすることもできますが——公式Pythonをインストールする手順としました。

**目的**

- システムにプリインストールされているPythonとは別に、開発用のPythonをインストールする

**やること**

- Pythonのインストール

**手順**

- [公式サイト](https://www.python.org/downloads/mac-osx/)より、インストーラをダウンロードしてインストールする。必ずしも最新版が良いとは限らないので、バージョンは吟味する。本稿執筆時点（2018/08/16）では、3.6.6が良いと思われる。

**補足**

- 公式サイトからインストールした場合、Hombrewとは異なり、アンインストールがコマンド一発では済みません。具体的な手順は、参考サイトの二番目、三番目をご参照ください。

**参考サイト**

- [心がHomebrewで旧バージョンのパッケージを入れたがってるんだ](https://qiita.com/cokaholic/items/6db92c23b43d18bdab82)
- [本家Pythonのアンインストール for Mac](https://codeaid.jp/python-uninstall/)
- [公式サイトからMacにインストールしたPythonをアンインストールする方法](https://peachcle.com/uninstall-python-for-mac/)


## 手順5. Pipenvのインストール

**目的**

- サンドボックス化された、複数の環境を持てるようにする
- 仮想環境がプロジェクトディレクトリの下に作成されるようにする

**やること**

- Pipenvのインストール
- Bash設定ファイルの編集

**手順**

- ターミナルを起動し、以下コマンドを実行する。

```bash
$ pip3 install pipenv
$ echo 'export PIPENV_VENV_IN_PROJECT=true' >> ~/.bash_profile
```

**参考サイト**

- [Pipenvに移行した話](https://kashewnuts.github.io/2018/03/15/pipenv.html)
- [Pipenvで仮想環境をプロジェクトディレクトリの下に作る](http://dackdive.hateblo.jp/entry/2018/05/16/100000)


## 手順6. ワークスペースの作成

**目的**

- 開発物を体系的に管理できるようにする

**やること**

- ワークスペースディレクトリの作成

**手順**

- Finderを起動し、適当な箇所に、手動でディレクトリを作成する。（コマンドで作成しても可。）


##  手順7. 仮想環境の作成

**目的**

- 開発用の仮想環境を作成する
- 科学技術計算などを中心とした数多くのモジュールやツールをインストールする

**やること**

- プロジェクトディレクトリの作成
- 仮想環境の作成
- パッケージのインストール

**手順**

- ターミナルを起動し、後述の一連のコマンドを実行する。内容としては、ワークスペースに移動し、プロジェクトディレクトリを作成。その中に移動し、コマンド`pipenv install`により仮想環境を作成——このとき、手順4でインストールしたPythonが、自動検出される。`pipenv shell`で仮想環境に入る。仮想環境内で`python -V`し、Pythonのバージョンが3.x.xであることを確認。コマンド`exit`で、仮想環境を抜ける。なお、`python -V`した際に、大量のメッセージが出力されてしまった人は補足参照。

```bash
$ cd <ワークスペース>
$ mkdir <プロジェクト>
$ cd <プロジェクト>
$ python -V
$ pipenv install
$ python -V
$ pipenv shell
$ python -V
$ exit
$ python -V
```

- プロジェクト直下の`Pipfile`をエディタ（テキストエディット等）で開き、\[packages\]の下に以下記載する。内容は、Anaconda相当のパッケージのインストールを指示している。こんなにたくさん不要という方は、必要なものだけを都度インストールしていって頂いても構わない。

```
[packages]
appdirs = "*"
astropy = "*"
"backports.shutil-get-terminal-size" = "*"
beautifulsoup4 = "*"
bitarray = "*"
bkcharts = "*"
blaze = "*"
bokeh = "*"
boto = "*"
Bottleneck = "*"
colorama = "*"
contextlib2 = "*"
cryptography-vectors = "*"
cytoolz = "*"
distributed = "*"
fastcache = "*"
filelock = "*"
future = "*"
gevent = "*"
glob2 = "*"
gmpy2 = "*"
h5py = "*"
imageio = "*"
jupyter = "*"
jupyterlab = "*"
keyring = "*"
lxml = "*"
mkl-fft = "*"
mkl-random = "*"
mpmath = "*"
nltk = "*"
nose = "*"
numba = "*"
numpydoc = "*"
olefile = "*"
openpyxl = "*"
partd = "*"
"path.py" = "*"
pathlib2 = "*"
patsy = "*"
pep8 = "*"
pipdeptree = "*"
pkginfo = "*"
ply = "*"
pycodestyle = "*"
pycosat = "*"
pycrypto = "*"
pycurl = "*"
pyflakes = "*"
pylint = "*"
pyodbc = "*"
PySocks = "*"
pytest-astropy = "*"
QtAwesome = "*"
rope = "*"
scikit-image = "*"
scikit-learn = "*"
seaborn = "*"
service-identity = "*"
singledispatch = "*"
sortedcollections = "*"
spyder = "*"
statsmodels = "*"
sympy = "*"
tables = "*"
Twisted = "*"
typing = "*"
unicodecsv = "*"
xlrd = "*"
XlsxWriter = "*"
xlwings = "*"
xlwt = "*"
tensorflow = "*"
keras = "*"
```

- ターミナルを起動し、一連のコマンドを実行する。なお、環境変数をエクスポートするのは、PycURLのビルドのため。PycURLをインストールしない場合は、エクスポートをスキップして頂いて構わない。

```bash
$ cd <プロジェクト>
$ export PYCURL_SSL_LIBRARY=openssl
$ export LDFLAGS=-L/usr/local/opt/openssl/lib
$ export CPPFLAGS=-I/usr/local/opt/openssl/include
$ pipenv install
```

**補足**

- `python -V`と入力する際、間違えて小文字で`python -v`と打つと、突如大量の文字列がターミナルに表示され、驚くかもしれません。これは、結論的に言うと、何も問題ありません。単にPythonを対話モードで、かつverbose（冗長）オプション付きで起動したために起きる現象です。あせらず、`quit()`と入力し、対話モードを抜けてください。抜ける際にも、`clear`だの`destroy`だのと言ってビビらせてくれますが、単に終了処理をしているだけなので、安心してください。
- [CPUの拡張命令を有効にするため、自身でTensorFlowをビルド](https://qiita.com/tanuk1647/items/31e7c943b98e090d27e2)した場合の`Pipfile`の記載は以下のとおりとなります。

```
xlwt = "*"
tensorflow = {path = "<wheelファイル保管ディレクトリへの絶対パス>/tensorflow-1.x.x-cp36-cp36m-macosx_10_x_x86_64.whl"}
keras = "*"
```

- LDFLAGSやCPPFLAGSについては、`brew info openssl`すると、ひっそりと教えてくれます。

```bash
$ brew info openssl
openssl: stable 1.0.2p (bottled) [keg-only]
SSL/TLS cryptography library
〜（中略）〜
For compilers to find this software you may need to set:
    LDFLAGS:  -L/usr/local/opt/openssl/lib
    CPPFLAGS: -I/usr/local/opt/openssl/include
For pkg-config to find this software you may need to set:
    PKG_CONFIG_PATH: /usr/local/opt/openssl/lib/pkgconfig
```

- 仮想環境は、プロジェクト内で、コマンド`pipenv --rm`を実行すれば削除されます。定義ファイル`Pipfile`と`Pipfile.lock`は残るので、環境の再構築や移行も容易です。

**参考サイト**

- [python -vを実行した時のエラーっぽい標準出力について](https://ja.stackoverflow.com/questions/41096/python-v%E3%82%92%E5%AE%9F%E8%A1%8C%E3%81%97%E3%81%9F%E6%99%82%E3%81%AE%E3%82%A8%E3%83%A9%E3%83%BC%E3%81%A3%E3%81%BD%E3%81%84%E6%A8%99%E6%BA%96%E5%87%BA%E5%8A%9B%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6)


## 手順8. Jupyter Notebookの設定

**目的**

- Jupyter Notebookから、仮想環境を選択できるようにする
- グラフのインライン表示、および、タイトルやラベルの日本語表示を可能とする
- プログラミングやマークダウンを快適に行えるようにする

**やること**

- 仮想環境をJupyter Notebookのカーネルとして追加
- iPythonのプロファイルの作成、編集、キャッシュのクリア
- 日本語等幅フォント（日本語と英語の幅が2:1のもの）のインストール
- 背景色が黒基調となるようなスタイルシートのダウンロード、編集

**手順**

- ターミナルを起動し、以下コマンドを実行する。

```bash
$ cd <プロジェクト>
$ pipenv run jupyter kernelspec list
$ pipenv run ipython kernel install --user --name=<仮想環境名> --display-name=<表示名>
$ pipenv run jupyter kernelspec list
```

- プロジェクト内で、コマンド`pipenv run ipython profile create`を実行する。作成されたプロファイル（`~/.ipython/profile_default/ipython_kernel_config.py`）の最下行に以下を追加する。追加後、もし、キャッシュ（`~/.matplotlib/fontList.json`）が存在すれば、削除する。

```python
## Setting to display graph inline
c.InteractiveShellApp.exec_lines = ['%matplotlib inline']

## Settings for displaying Japanese
c.InlineBackend.rc = {
    'font.size': 11,
    'font.family': 'Osaka',
    'figure.figsize': (6.0, 4.0),
    'savefig.dpi': 80,
    'axes.titlesize': 12
}
c.InlineBackend.figure_formats = set(['png', 'retina'])
```

- [Ricty Diminishedの公式サイト](http://www.rs.tus.ac.jp/yyusa/ricty_diminished.html)から、フォントファイル一式をダウンロードする。Font Bookを起動し、ダウンロードしたフォントファイルを追加する。
- [Oleg Levitsky氏のGitHub Gist](https://gist.github.com/levabd/eb2db79567fe737b8232db046ee12eb3)より`custom.css`をダウンロードし、`~/.jupyter/custom/`直下に保存する。保存したcssを三箇所編集する。
    - プログラミング用フォントの`font-family`に`"Ricty Diminished"`を追加（49行目）
    - プログラミング用フォントの`font-size`を`10pt`に変更（58行目）
    - ツールバーの非表示設定をコメントアウト（231行目）

```css
〜（中略）〜
/* 
  SET THE CODE/MONOSPACE FONT 

  I prefer Bitsream Vera Sans Mono, which is freely downloadable here:
  http://www.dafont.com/bitstream-vera-mono.font
  However, there are plenty of alternatives at http://programmingfonts.org/
  in which case, add your preferred font to the stack below.
*/
〜（中略）〜
div.output pre,
div.output code,
.rendered_html pre,
.rendered_html code,
div.completions select,
div.container pre {
    font-family: "Ricty Diminished", "Bitstream Vera Sans Mono", Monaco, monospace;
}

div.output pre,
div.output code,
.rendered_html pre,
.rendered_html p code,
div.completions select,
div.container pre {
    font-size: 10pt;
}
〜（中略）〜
/* NOTEBOOK AND EDITOR INTERFACE */


/* comment out the following line to unhide the toolbar */

div#maintoolbar {
/*    display: none !important; */
}
〜（中略）〜
```

**補足**

- 当初、[jupyterthemes](https://github.com/dunovank/jupyter-themes)の利用も検討しました。コマンドでテーマを切り替えられる素晴らしいツールですが、プログラミングやマークダウン時に日本語等幅フォント（日本語と英語の幅が2:1のもの）を使えるようにすることがどうしてもできなかったので、別の手段をとることにしました。マークダウン時、日本語を含む表を作成する際に、罫線が揃うようにしたかったためです。スタイルシートの作者である[Oleg Levitsky](https://gist.github.com/levabd)氏、および、その先人達に感謝します。
- お気に入りの日本語等幅フォント（日本語と英語の幅が2:1のもの）があれば、そちらを利用しても構いません。フォントのファミリー名は、Font Bookで確認することができます。

**参考サイト**

- [Jupyterで複数カーネルを簡単に選択するための設定](https://qiita.com/tomochiii/items/8b937f15c79a0c3eae0e)
- [%matplotlib inlineを毎回書かなくて済む方法](https://qiita.com/noguchi0123/items/2c83e30e274e5a51cb41)
- [Jupyterで日本語ラベルを使ったグラフを描画する](https://qiita.com/hagino3000/items/1b54acc01483ccd0ac72)


## 手順9. PDFの設定

**目的**

- 作成したノートブックをLateX経由でPDFダウンロードできるようにする
- PDFの図表が、次ページでなく、なるべくその場所に表示されるようにする
- PDFに日本語が出力されるようにする

**やること**

- MacTexのインストール
- LaTeX関連ファイルの作成、編集

**手順**

- コマンド`brew cask install mactex`を実行する。
- `<プロジェクト>/.venv/lib/python3.6/site-packages/nbconvert/templates/latex`直下の`base.tplx`を三箇所編集する。
    - フォントを指定する設定、段落のインデントを行う設定、`jalinebreak.sty`を読み込む設定を追加（16行目と17行目の間、`\usepackage[T1]{fontenc}`の直下に、`% Settings for displaying Japanese`以下の5行を追加）
    - PDFの図表が、次ページでなく、なるべくその場所に表示されるように指定（27行目と28行目の間、`\usepackage{graphicx}`の直下に、`% set default figure placement to htbp`以下の4行を追加）
    - 日本語フォントの指定を追加（175行目と177行目の間、`\begin{document}`の下に、`% Settings for displaying Japanese`以下の4行を追加）

```TeX
〜中略〜
%===============================================================================
% Abstract overrides
%===============================================================================

((* block header *))
    ((* block docclass *))((* endblock docclass *))
    
    ((* block packages *))
    \usepackage[T1]{fontenc}
    % Settings for displaying Japanese
    \usepackage{fontspec}
    \setlength{\parindent}{11pt}
    \usepackage{indentfirst}
    \usepackage{jalinebreak}
    % Nicer default font (+ math font) than Computer Modern for most use cases
    \usepackage{mathpazo}

    % Basic figure setup, for now with no caption control since it's done
    % automatically by Pandoc (which extracts ![](path) syntax from Markdown).
    \usepackage{graphicx}
    % set default figure placement to htbp
    \makeatletter
    \def\fps@figure{htbp}
    \makeatother
	% We will generate all images so they have a width \maxwidth. This means
    % that they will get their normal width if they fit onto the page, but
    % are scaled down if they would overflow the margins.
〜中略〜
((* block body *))
    \begin{document}

    % Settings for displaying Japanese
    \setmainfont[BoldFont=HiraginoSans-W5]{HiraMinProN-W3}
    \setsansfont{HiraginoSans-W5}
    \setmonofont{RictyDiminished-Regular}
    
    ((* block predoc *))
〜中略〜
```

- ターミナルを起動し、以下コマンドを実行する。

```bash
$ mkdir -p ~/texmf/tex/latex/local
$ touch ~/texmf/tex/latex/local/jalinebreak.sty
```

- 作成された設定ファイル（`jalinebreak.sty`）に以下（日本語の段落を右端で折り返す設定）を記載する。

```TeX
\XeTeXlinebreaklocale "ja"
\XeTeXlinebreakskip=0pt plus 1pt
\XeTeXlinebreakpenalty=0

\def\<{\@ifstar{\zx@hwback\nobreak}{\zx@hwback\relax}}
\def\zx@hwback#1{\leavevmode#1\hskip-.5em\relax}
```

**補足**

- PDFダウンロード時、図表が次ページに送られる現象を当初どうしても解決できませんでした。突破口となったのは、参考サイトの二番目、@[cawpea](https://qiita.com/cawpea)氏の投稿でした。氏の投稿を参考に、PandocのLaTeX用テンプレートを生成。Jupyter NotebookのMarkdownをコマンド`pandoc`でテンプレートを用いてLaTeXに変換。通常版とDIFFをとることにより、ようやく必要な設定が見えてきた次第です。深く感謝します。
- `base.tplx`の設定では、mainfontに明朝体、BoldFontにその太字、sansfontにゴシック体、monofontに等幅フォントを指定すると、市販の多くの書籍のような書体になります。お気に入りのフォントがあれば、そちらを利用しても構いません。フォントのPostScript名やファミリー名は、Font Bookで確認することができます。
- 私にとってTeXまわりは未知の領域ですので、参考サイトの三番目、@[masa-ita](https://qiita.com/masa-ita)氏の投稿に出会わなければ、ドツボにハマるところだったでしょう。御礼申し上げます。

**参考サイト**

- [Installation — nbconvert 5.3.2.dev0 #installing-tex](https://nbconvert.readthedocs.io/en/latest/install.html#installing-tex)
- [Pandocを使ってMarkdownを整形されたHTMLに変換する](https://qiita.com/cawpea/items/cea1243e106ababd15e7)
- [日本語のJupyter NotebookをPDFとしてダウンロードする](https://qiita.com/masa-ita/items/8d5ebe8afe0d580af184)
- [日本語対応のLaTexで自動字下げされない件(＋字下げしない方法)](https://qiita.com/fantm21/items/9e4512d3af605dae1734)


## 手順10. GNU Core Utilitiesのインストール

**目的**

- macOSにプリインストールされているBSD系コマンドを、よりメジャーなGNU/Linux系コマンドに置き換える

**やること**

- GNU Core Utilitiesのインストール

**手順**

- ターミナルを起動し、以下コマンドを実行する。

```bash
$ brew install coreutils
$ echo 'export PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH"' >> ~/.bash_profile
$ echo 'export MANPATH="/usr/local/opt/coreutils/libexec/gnuman:$MANPATH"' >> ~/.bash_profile
$ echo "alias ls='ls --color=auto'" >> ~/.bashrc
$ source ~/.bash_profile
$ source ~/.bashrc
```

- 同様に、diffutils、colordiff、findutils、grepあたりをインストールしておく。コマンド`brew install <パッケージ名>`でよい。追加すべき`PATH`があれば、インストール後に注意事項（`Caveats`）として表示される。

**参考サイト**

- [テキスト処理のための標準的なコマンド群の OS X への導入手順](https://qiita.com/eumesy/items/3bb39fc783c8d4863c5f)
- [散々既出で今更だけどmacOSデフォルトのgrepがめちゃ遅だった](https://amaya382.hatenablog.jp/entry/2017/12/25/180700)


## 手順11. 動作確認

**目的**

- 正しく環境構築できていることを確認する

**やること**

- Jupyter Notebookの背景色が白でなく黒基調であることの確認
- Jupyter Notebookから仮想環境を選択できることの確認
- Kerasが実行できることの確認
- グラフがインライン表示され、ラベルに日本語が表示されていることの確認
- マークダウンが日本語等幅フォントで行えることの確認
- ノートブックをPDF形式でダウンロードでき、日本語が出力されていることの確認
- GNU Core Utilitiesがインストールできていることの確認

**手順**

- 以下コマンドで、Jupyter Notebookを起動し、背景色が白でなく黒基調であることを確認する。

```bash
$ cd <プロジェクト>
$ pipenv run jupyter notebook
```

- 新規ノートブックを作成し、このとき、作成した仮想環境を選択する。（選択できることを確認する。）

- セルに以下のKerasコードを貼り付け、`[shift] + [return]`で実行する。実行できること、グラフが表示されること、および、グラフのラベルに日本語が表示されていることを確認する。



```python
from itertools import cycle, islice
from numpy import array, eye, shape, sum, unique
import keras.optimizers as opt
import keras.backend as K
import keras.callbacks as clb
import keras.models as mdl
import keras.layers as lyr
import keras.losses as lss
import matplotlib.pyplot as plt

unit = [0, 0, 1, 0, 2, 1, 0, 0, 1, 2, 0, 1, 0, 0, 3]
raw_data = array([i for i in islice(cycle(unit), 0, 3015)])

num_of_class = len(unique(unit))
onehot_data = eye(num_of_class)[raw_data]

t_inputs, t_targets = [], []
num_steps = len(unit)

for i in range(len(raw_data) - num_steps):
    t_inputs.append(raw_data[i : i + num_steps])
    t_targets.append(onehot_data[i + num_steps])

inputs = array(t_inputs).reshape(len(t_inputs), num_steps, 1)
targets = array(t_targets)

class Model:
    # モデルに関するパラメータ
    units = 32
    
    optimizer = opt.Adam()
    
    # 訓練に関するパラメータ
    batch_size = 15
    epochs = 10
    
    callbacks = []

    factor = 0.5
    verbose = 1
    reduce_lr_on_plateau = clb.ReduceLROnPlateau(factor=factor,
                                                 verbose=verbose)
    callbacks.append(reduce_lr_on_plateau)

    validation_split = 0.1
    
    # モデルの初期化
    def __init__(self):
        self.__model = mdl.Sequential()
            
    # 訓練
    def train(self, inputs, targets):
        print('訓練を行うので、お待ちください。')

        # モデルの実装
        self.__model.add(lyr.LSTM(Model.units))
        self.__model.add(lyr.Dense(targets.shape[1], activation=K.softmax))
        self.__model.compile(loss=lss.categorical_crossentropy, optimizer=Model.optimizer)

        # 訓練実施
        hist = self.__model.fit(inputs, targets,
                                batch_size=Model.batch_size
                                , epochs=Model.epochs
                                , callbacks=Model.callbacks
                                , validation_split=Model.validation_split
                               )
        
        # 訓練状況の可視化
        loss = hist.history['loss']
        val_loss = hist.history['val_loss']
        
        plt.figure()
        plt.plot(range(1, len(loss) + 1),
                 loss, marker='.', label='訓練データ')
        plt.plot(range(1, len(val_loss) + 1),
                 val_loss, marker='.', label='テストデータ')
        plt.legend(loc='best', fontsize=10)
        plt.grid()
        plt.xlabel('エポック')
        plt.ylabel('損失')
        plt.yscale('log')
        plt.grid(which='major',color='black',linestyle='-')
        plt.grid(which='minor',color='black',linestyle='-')
        plt.show()
        
    # 予測
    def predict(self, inputs):
        return self.__model.predict(inputs)

class FizzBuzz:
    def __init__(self, model):
        self.__model = model
    
    def fizzbuzz(self, n):
        unit = [0, 0, 1, 0, 2, 1, 0, 0, 1, 2, 0, 1, 0, 0, 3]
        i = 1
        answer = []
        for i in range(i, n + 1):
            t_inputs = array ([unit])
            inputs = t_inputs.reshape(len(t_inputs), len(unit), 1)
            prd = self.__model.predict(inputs) [0].argmax()
            if prd == 0:
                answer.append(str(i))
            elif prd == 1:
                answer.append('Fizz')
            elif prd == 2:
                answer.append('Buzz')
            elif prd == 3:
                answer.append('FizzBuzz')
            else:
                answer.append(str(i))
            unit.pop(0)
            unit.append(prd)
        return answer

m = Model()
m.train(inputs, targets)

fb = FizzBuzz(m)

print(fb.fizzbuzz(100))
```

- 新規にセルを追加し、タイプを`Markdown`に切り替える。以下文字列を貼り付け、罫線が揃っていることを確認する。`[shift] + [return]`で表を描画する。

```
| 日本語と         | 英語が混じっても | 罫線が         | ずれない        |
|:-----------------|-----------------:|:--------------:|:---------------:|
| Even if Japanese | and English mix, | the ruled line | does not shift. |
| 日本語と         | 英語が混じっても | 罫線が         | ずれない        |
| Even if Japanese | and English mix, | the ruled line | does not shift. |
| 日本語と         | 英語が混じっても | 罫線が         | ずれない        |
```

- `File`から、LaTex経由のPDF形式でダウンロードし、ダウンロードできること、日本語が出力されていることを確認する。
- Notebookを保存し、閉じる。ブラウザを閉じる。ターミナルを`[control] + [C]`で停止する。
- 新規にターミナルを起動し、コマンド`ls`を実行する。ホームディレクトリ内のディレクトリが紫色で表示されていることを確認する。コマンド`bash`を実行し、コマンド`ls`を実行する。ホームディレクトリ内のディレクトリが紫色で表示されていることを確認する。コマンド`exit`を二回実行し、ターミナルを閉じる。

**補足**

- 学習状況を可視化する部分は、参考サイトを参考にさせて頂きました。御礼申し上げます。

**参考サイト**

- [KerasではじめるDeepLearning](https://dev.classmethod.jp/machine-learning/introduction-keras-deeplearning/)


## 補足）Pipenvについての参考サイト

**公式**

- [Pipenv: 人間のためのPython開発ワークフロー](https://pipenv-ja.readthedocs.io/ja/translate-ja/)
- [Pipenvと仮想環境](https://pipenv-ja.readthedocs.io/ja/translate-ja/install.html)
- [Pipenvの基本的な使い方](https://pipenv-ja.readthedocs.io/ja/translate-ja/basics.html)

**ユーザー**

- [pipenv を使ってみる](https://nonylene.hatenablog.jp/entry/2017/04/14/195925)
- [Python の依存パッケージ管理/環境切り分けツール pipenv の紹介](https://utgwkk.hateblo.jp/entry/2017/09/05/110209)
- [Pipenvを使ってみる](https://minus9d.hatenablog.com/entry/2018/04/29/145146)
- [Pythonで、Pipenvを使う](https://torina.top/detail/458/)
- [pipenv を使ってみたのでメモ](https://qiita.com/subarunari/items/dcbdad68ba1809b721b9)