AIを学習するための環境準備

# はじめに
自宅PCでAIについて勉強をしたいと思って書籍を買ったけど、Pythonを実行できる環境がない。
できるだけPCの中は汚したくない。
ということで、Python環境構築について調べてみました。

# 環境
- 自宅PC
- Windows11
- VisualStudioCodeインストール済
- Pythonインストール済

https://www.python.org/downloads/

# WSL(Ubuntu)の準備
WindowsでLinuxを動かせる環境を準備します。
### WSLインストール
以下の操作でインストールします。
1. Windowsの機能の有効化または無効化を開く
2. Linux用Windowsサブシステムをチェックする
3. カーネル更新プログラムをインストール

https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi

## WSL環境設定
PowerShellを開いてコマンドで設定します。
### WSL更新
```
> wsl --update
```

### バージョン設定
```
> wsl --set-default-version 2
> wsl --status
既定のバージョン: 2
> wsl --version
WSL バージョン: 2.2.4.0
```

### Ubuntu24.04LTSをインストール
インストールするときに、ユーザー名とパスワードを設定するので忘れないように控えておくこと！
※ちなみにWindowsStoreからもインストール可能です。（今回はそうしたので既にインストールされていますと表示されている）
```
> wsl --install -d Ubuntu-24.04
```
インストールされているディストリビューションを表示。
```
> wsl -l -v
  NAME            STATE           VERSION
* Ubuntu-24.04    Running         2
```

### 起動・接続
Ubuntu指定しなくても、`wsl`だけでも入れるかも。
```
> wsl -d Ubuntu-24.04
```

## Ubuntu更新
パッケージ管理リストとパッケージのアップデート。
```
$ sudo apt update
$ sudo apt -y upgrade
```

# Python設定
WSL(Ubuntu)上で実行します。

## pipインストール
Pythonのパッケージ管理ライブラリをインストール。
```
$ sudo apt -y install python3-pip
```

## pythonコマンドで実行できるようにエイリアス設定
```
$ sudo vim ~/.bashrc
```
以下を追記。
```
# Python
alias python="python3"
alias pip="pip3"
```
以下のコマンドで反映し、pythonコマンドが通るようになっていることを確認。
```
$ source ~/.bashrc
$ python --version
Python 3.12.3
```

# pyenv
Pythonのバージョン管理ツール。
好きなバージョンに切り替えることができるようになる。
PythonだけでなくAnacondaとか、好きに変更できるようになる。

まずは、前提パッケージをインストール。
```
$ sudo apt -y install build-essential libffi-dev libssl-dev zlib1g-dev liblzma-dev libbz2-dev libreadline-dev libsqlite3-dev libopencv-dev tk-dev git
```

gitに置かれてるのでクローンで持ってくる。
```
$ git clone <https://github.com/pyenv/pyenv.git> ~/.pyenv
```

bashで使えるように設定。
```
$ echo '' >> ~/.bashrc
$ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc
$ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc
$ echo 'eval "$(pyenv init --path)"' >> ~/.bashrc
$ source ~/.bashrc
```

バージョン確認できればインストール成功。
```
$ pyenv -v
pyenv 2.4.13
```

インストール可能なPythonバージョンを確認。
```
$ pyenv install --list
```

好きなバージョンをインストールし、インストールしたバージョン一覧確認。
`system (set by /home/********/.pyenv/version)`と書かれているのは、システムのデフォルトのものバージョンが使われているということ。

利用中のバージョンだけ確認するのであれば、`pyenv version`で確認できる。
```
$ pyenv install 3.12.6
$ pyenv versions
* system (set by /home/********/.pyenv/version)
  3.12.6
```

## システム全体のPythonバージョンを指定する
```
$ pyenv global 3.12.6
```

## プロジェクトディレクトリだけPythonバージョンを指定する
プロジェクトディレクトリで以下のコマンド。
`.python-version`というバージョンが書かれたファイルが作られる。

```
$ pyenv local 3.12.6
```

# (参考)venv
仮想環境を作ることができ、pipによるパッケージ管理をプロジェクトごとに分けることができるようになる。

後述しているpoetryでも仮想環境を作ることができたので、venvは使わなくてもいいかもしれない。venvを使わない場合は飛ばしても問題ない。
```
$ sudo apt -y install python3-venv
```

venvという仮想環境名でモジュールを動かすと仮想環境が作成される。
```
$ python -m venv venv
```

有効化。
```
$ source ./venv/bin/activate
```

無効化。
```
(venv)$ deactivate
```

# Poetry
プロジェクトごとに仮想環境を作ることができ、さらにパッケージ管理までこなしてくれる便利なもの。venvではなくてこちらを採用した。

https://cocoatomo.github.io/poetry-ja/

## インストール
pipとsetuptoolsを最新にしてからインストールする。
```
$ pip install --upgrade pip
$ pip install -U pip setuptools
$ pip install poetry
```

## 初期設定
初期設定する。設定を聞かれるがデフォルトで良さそう。後で変更できるっぽい。
設定が終わると、pyproject.tomlファイルが作成される。
```
$ poetry init

This command will guide you through creating your pyproject.toml config.

Package name [python]:
Version [0.1.0]:
Description []:
Author [None, n to skip]:  n
License []:
Compatible Python versions [^3.12]:

Would you like to define your main dependencies interactively? (yes/no) [yes]
You can specify a package in the following forms:
  - A single name (requests): this will search for matches on PyPI
  - A name and a constraint (requests@^2.23.0)
  - A git url (git+https://github.com/python-poetry/poetry.git)
  - A git url with a revision (git+https://github.com/python-poetry/poetry.git#develop)
  - A file path (../my-package/my-package.whl)
  - A directory (../my-package/)
  - A url (<https://example.com/packages/my-package-0.1.0.tar.gz>)

Package to add or search for (leave blank to skip):

Would you like to define your development dependencies interactively? (yes/no) [yes]
Package to add or search for (leave blank to skip):

Generated file

[tool.poetry]
name = "python"
version = "0.1.0"
description = ""
authors = ["Your Name <you@example.com>"]
readme = "README.md"

[tool.poetry.dependencies]
python = "^3.12"

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

Do you confirm generation? (yes/no) [yes]
```

## 仮想環境接続
新規シェルで仮想環境構築。
```
$ poetry shell
Spawning shell within /mnt/c/Users/********/Documents/pyproject/.venv
. /mnt/c/Users/alpha/Documents/pyproject/.venv/bin/activate
```

## 仮想環境から抜ける
抜けるときはexitで抜ける。

```
$ exit
```

## 仮想環境設定
プロジェクトディレクトリ内に仮想環境の設定を作成する。
これで仮想環境を作ると、.venvディレクトリが作成される。
```
$ poetry config virtualenvs.in-project true
```

## 仮想環境の確認
.venvという仮想環境が動いている。exitで抜けても動きっぱなしであることが分かる。
```
$ poetry env list
.venv (Activated)
```

```
$ poetry env info

Virtualenv
Python:         3.12.6
Implementation: CPython
Path:           /mnt/c/*****/pyproject/.venv
Executable:     /mnt/c/*****/pyproject/.venv/bin/python
Valid:          True

Base
Platform:   linux
OS:         posix
Python:     3.12.6
Path:       /home/*****/.pyenv/versions/3.12.6
Executable: /home/*****/.pyenv/versions/3.12.6/bin/python3.12
```

## 仮想環境削除
.venvのディレクトリごと削除する。
```
$ rm -rf /mnt/c/Users/********/Documents/pyproject/.venv
```

## ライブラリ追加＆削除
ライブラリを追加する場合、`poetry add {パッケージ名}`で追加できる。
poetry.lockファイルが作られ、tomlファイルにライブラリ情報が追加される。

削除したい場合は、`poetry remove {パッケージ名}`で削除できる。

使いそうなものを入れておくだけ入れておく。
```
$ poetry add jupyterlab ipykernel jupyter-core
$ poetry add matplotlib pandas torch numpy
$ poetry add transformers gradio accelerate langchain
```

新規プロジェクトディレクトリでtomlファイルを使って一括インストールしつつ仮想環境を構築する場合はこう。
```
$ poetry install
```

## インストール済みのライブラリを表示
```
$ poetry show
```

## poetryの現在の設定を確認
```
$ poetry config --list
```

# JupyterLab設定
## 拡張機能追加
まずは、VSCodeの拡張機能`Jupyter`を追加しておく。

## カーネル登録
```
$ poetry run python -m ipykernel install --user --name=practice --display-name "Python (Practice)"
```

## 起動時のtoken固定化
起動するたびに毎回tokenを問われます。`qwertyuiop`にしました。
```
$ poetry run jupyter lab --generate-config
Writing default config to: /home/XXXXXX/.jupyter/jupyter_lab_config.py
$ echo "c.ServerApp.token = 'qwertyuiop'" >> /home/XXXXXX/.jupyter/jupyter_lab_config.py
```

## JupyterLab起動
起動すると、jupyterserverのアドレスが表示されるので控える。
ブラウザで開くこともできる。
```
$ poetry run jupyter lab
```

## テスト用にJupyterNotebookファイルを作成する
VSCodeで[ctrl]+[shift]+[P]でコマンドパレットを開く。

`Jupyter: Create New Juptyer Notebook`を選択。
JupyterNotebookが新規に作られるので、プロジェクトディレクトリに好きな名前で保存。

## カーネルを選択する
作ったJupyterNotebookを開き、右上の設定から、`別のカーネルを選択`→`既存のJupyterServer`→`jupyterserverのアドレスを設定`→`作成したカーネルを選択`

これで仮想環境上で動かしているjupyterserverと接続ができるようになった。

## .pyファイルをJupyterライクに使う
VSCodeを使っている場合、.pyファイルのプログラムに`#%%`をつけるだけでJupyterライクに使える。
```python
#%%
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer

# モデルの読み込み
model_name = "cyberagent/open-calm-small"
model = AutoModelForCausalLM.from_pretrained(model_name)
# トークナイザー(単語や文字などのトークンに分割する機能)の読み込み
tokenizer = AutoTokenizer.from_pretrained(model_name)

# テキストをトークン化
# return_tensors="pt"は、PyTorchのテンソル形式で返すという意味
inputs = tokenizer("日本の首都はどこですか？", return_tensors="pt")
# モデルで文字の生成を行う
tokens = model.generate(
    **inputs,
    max_new_tokens=30,                     # 与えられた文字列のあとに最大何tokenまで生成するか
    # max_length=10,                       # 最大文字列を指定、max_new_tokensを設定している場合は使えない
    do_sample=True,                        # 生成確率の最大のtokenを出していくかどうか
    top_k=5,                               # do_sampleがTrueのときに出す候補のtoken数
    temperature=1.1,                       # どれくらい多様な生成をするかの調整値(1.0以上だと創造的なキーワードが選出される可能性が高まる)
    repetition_penalty=1.5,                # 同じ単語やフレーズが繰り返し生成されるのを抑制するためのパラメータ
    eos_token_id=tokenizer.encode("。"),   # 文末のトークンIDを指定
    pad_token_id=tokenizer.pad_token_id,   # トークン化されたテキストの長さを揃えるために使用されるパディングトークンのID
    num_return_sequences=3,                # いくつ生成するかを指定、例えば2を指定するとtokens[0],tokens[1]が生成される
    )

# デコードすると文字が得られる。
for i in range(len(tokens)):
    output = tokenizer.decode(
        tokens[i],                # 生成された文章の配列
        skip_special_tokens=True  # デコード時に特殊トークンをスキップさせる
        )
    print(output)
```

# おわりに
なんとか環境だけできました。
streamlit使って簡単にAIチャットアプリ作れたりするみたいなので、色々と試して遊んでみようと思います。

こちらの記事はctc Advent Calendar 2024の記事となります。
この後もctc(中部テレコミュニケーション株式会社)のメンバーが技術にまつわる知見を投稿していきますのでご期待ください。

https://qiita.com/advent-calendar/2024/ctc