pythonをRStudioで使うのはreticulate
パッケージによりだいぶ楽になった。
ただpythonにおけるdeep learningの代表的パッケージであるtensorflow
をRStudioで使う際に少しつまづいたのでメモです。
pythonの環境をどうやって構築するか?
Rではrenv
パッケージを使っている。ではpythonでは?
pythonはRよりも環境が複雑で変化も早そうなので、環境構築は重要。
今回はpython公式が推奨しているっぽいvenv
を使う。
最初global環境でそのままやろうとしたが上手くいかず挫折。Dockerとかも有力だと思う。
venvを使って仮想環境を用意
- pythonがインストールされているか確認
- homebrewなりでインストールしておく
- PATHを通しておく
- 作業ディレクトリにて、terminalで以下のコマンドを実行し
.venv
フォルダを作成
pythonライブラリをインストール
source .venv/bin/activate
source .venv/bin/activate
は、ライブラリをインストールするときは毎回実行する必要があります!
まちがってglobal環境を汚さないように!
- ライブラリをインストール
tensorflow
のほか、numpy
も必須(tensorflow
をインストールしたときに入る)
- M1 macでGPUを使いたい場合は
tensorflow-metal
もインストールする
pip install tensorflow-macos
pip install tensorflow-metal
RStudioでpythonを使う
pythonの場所を指定
- RStudioでpythonを使うには、RStudioにpythonの場所を教えてやる必要がある
- 今回は
.venv
内のpythonを使いたいので、作業ディレクトリに.Rprofile
を作成し、以下のコードを書く
renv
を使っている場合は、.Rprofile
が既に作成されていると思うので、その中に追記する
# renv起動
source("renv/activate.R")
# pythonの場所を指定
Sys.setenv(RETICULATE_PYTHON = ".venv/bin/python3")
pythonの場所の指定はrenv
の起動より後に行う必要がある。もし先にpythonの場所を指定してしまうと、renv
を起動したときにpythonの場所が上書きされてしまい、上手くいかなくなる。
pythonを起動
- RStudioでpythonのコードを実行すると、
reticulate::repl_python()
が走ってコンソールがpythonになる
import sys
print(sys.version)
3.11.12 (main, Apr 8 2025, 14:15:29) [Clang 16.0.0 (clang-1600.0.26.6)]
- tensorflowを起動して、GPUが使えるかを確認
- physical_deviceでCPUとGPUの両方が表示されてればOK
import tensorflow as tf
tf.config.list_physical_devices()
[PhysicalDevice(name='/physical_device:CPU:0', device_type='CPU'), PhysicalDevice(name='/physical_device:GPU:0', device_type='GPU')]
ニューラルネットをやってみる
- チュートリアルとして、手書きのアルファベットを分類するモデルを作成してみる
- Rでデータを読み込んで、pythonに渡して
tensorflow
で分析
- 参考
library(tidyverse)
library(rsample)
library(reticulate)
データのダウンロード
# データのダウンロード
if (!dir.exists('data')) dir.create('data')
download.file('https://ai.stanford.edu/~btaskar/ocr/letter.data.gz', destfile = 'data/letter.data')
データの読み込み
- 列名はhttps://ai.stanford.edu/~btaskar/ocr/letter.namesより取得できる
- 詳細は以下の通り
- id: each letter is assigned a unique integer id
- letter: a-z
- next_id: id for next letter in the word, -1 if last letter
- word_id: each word is assigned a unique integer id (not used)
- position: position of letter in the word (not used)
- fold: 0-9 – cross-validation fold
- p_i_j: 0/1 – value of pixel in row i, column j
- letterとp_i_j(pixel)のみ使うのでそれ以外は削除
colname <- read_lines('https://ai.stanford.edu/~btaskar/ocr/letter.names')
data <-
read_tsv('data/letter.data', col_names = colname) |>
# letterとpixelだけ残す
select(id, letter, matches('p_\\d+_\\d+'))
データの前処理
df <-
data |>
mutate(
letter = factor(letter),
# pythonは0からはじまるので-1する(Rは1から)
letter_num = as.numeric(letter) - 1
)
split <- rsample::initial_split(df, prop = 0.9)
train <- rsample::training(split)
test <- rsample::testing(split)
- pythonに渡せる形にデータを変換
reticulate::np_array()
であらかじめndarray
にしておくと便利
train_x <-
train |>
select(!c(id, letter, letter_num)) |>
as.matrix() |>
np_array()
train_y <-
train |>
pull(letter_num) |>
np_array()
test_x <-
test |>
select(!c(id, letter, letter_num)) |>
as.matrix() |>
np_array()
test_y <-
test |>
pull(letter_num) |>
np_array()
ニューラルネットで学習
- 中間層が1つのニューラルネットを作成
- 入力層は16x8=128(ピクセル)
- 中間層は64次元
- 出力層はa-zの26分類
import tensorflow as tf
import numpy as np
# モデルの作成
model = tf.keras.Sequential([
tf.keras.layers.Dense(64, activation='relu'),
tf.keras.layers.Dense(26, activation='softmax')
])
model.compile(
optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy']
)
- rで作成したデータをpythonに渡して学習
r.train_x
でRのtrain_x
を参照できる
- pythonのオブジェクトを渡すときは
py$train_x
# モデルの学習
model.fit(r.train_x, r.train_y, epochs=10, verbose=2)
Epoch 1/10
1467/1467 - 8s - loss: 1.3177 - accuracy: 0.6413 - 8s/epoch - 6ms/step
Epoch 2/10
1467/1467 - 6s - loss: 0.9427 - accuracy: 0.7486 - 6s/epoch - 4ms/step
Epoch 3/10
1467/1467 - 6s - loss: 0.8788 - accuracy: 0.7642 - 6s/epoch - 4ms/step
Epoch 4/10
1467/1467 - 6s - loss: 0.8475 - accuracy: 0.7729 - 6s/epoch - 4ms/step
Epoch 5/10
1467/1467 - 6s - loss: 0.8340 - accuracy: 0.7759 - 6s/epoch - 4ms/step
Epoch 6/10
1467/1467 - 6s - loss: 0.8259 - accuracy: 0.7777 - 6s/epoch - 4ms/step
Epoch 7/10
1467/1467 - 6s - loss: 0.8233 - accuracy: 0.7786 - 6s/epoch - 4ms/step
Epoch 8/10
1467/1467 - 6s - loss: 0.8240 - accuracy: 0.7773 - 6s/epoch - 4ms/step
Epoch 9/10
1467/1467 - 6s - loss: 0.8218 - accuracy: 0.7789 - 6s/epoch - 4ms/step
Epoch 10/10
1467/1467 - 6s - loss: 0.8242 - accuracy: 0.7779 - 6s/epoch - 4ms/step
<keras.src.callbacks.History object at 0x177fd5910>
テストデータで評価
# モデルの評価
model.evaluate(r.test_x, r.test_y, verbose=2)
163/163 - 1s - loss: 0.8293 - accuracy: 0.7688 - 513ms/epoch - 3ms/step
[0.8292935490608215, 0.7687883377075195]