bookmark_borderPythonの or は「または」ではない

単にTrueかFalseを返す演算子ではない

Pythonの or は「または」の意味だと說明されることがあります。

x = 10

# x は 10 または 20
if x == 10 or x == 20:
    print("xは10か20です")

# 実行結果:xは10か20です

しかしこのコードの実行結果を見ると、 or は単なる「または」ではないことがわかります。

a = False
b = 123
print(a or b)

# 実行結果: 123
# Trueではない

じゃあ何なのか

公式ドキュメントには下記の說明があります。

式 x or y は、まず x を評価します; x が真なら x の値を返します; それ以外の場合には、 y を評価した結果値を返します。

docs.python.org – 6. 式 (expression)

オブジェクトを返す演算子

or は両端の値のうち、 最初にTrueと評価される値 を返します。

true_value_1 = 100
true_value_2 = 200

print(true_value_1 or true_value_2)

# 実行結果: 100

# true_value_1 or true_value_2 の中で、
# true_value_1 が最初にTrueと評価される値である → 100

両方がFalseと評されるなら、右側の値を返します。

false_value_1 = False
false_value_2 = 0
print(false_value_1 or false_value_2)

# 実行結果: 0

# false_value_1 or false_value_2 の中で、Trueと評価される値はなかった。
# false_value_2 が右側の値である → 0

※より正確には、返されるのは「値や式の評価結果」です。

つまりどういうことか

or が返すのは or の両端の値のどちらかです。どちらが返されるかは、その両端の値がTrueとFalseどちらに評価されるかによって決まります。

Pythonの or はJavaなどの言語と異なり、真偽値(True, False)しか受け取れない演算子ではありません。あらゆる値をオペランドに(つまりorの両側に)持つことができます。

つまり先に登場したif文は厳密に言うと下記の流れをたどっているということです。

x = 10
if x == 10 or x == 20: 
# ↓ 
# if True or False: # or の両端の式がまず計算される
# ↓
# if True: # orの左側の値がTrue。よってorは左側の値のTrueを返す
    print("xは10か20です")

# 実行結果: xは10か20です

両方ともFalseとなる場合は下記のとおりです。

x = 100000
if x == 10 or x == 20: 
# ↓ 
# if False or False: # or の両端の式がまず計算される
# ↓
# if False: # orの両端がFalse。よってorは右側のFalseを返す
    print("xは10か20です")

# 実行結果: (何も出力されない)

どう役立つのか

関数の引数のデフォルト値

関数の引数に偽と評価される値 (None 0 "" など)が渡された場合のデフォルト値を設定できます。

def greet(name=None):
    name = name or "Guest"
    print(f"Hello, {name}!")

greet()  # 出力: Hello, Guest!
greet("Alice")  # 出力: Hello, Alice!

PHPの言語でサポートされているNull合体演算子の代わりのように使えるということです。

hoge = None

# if hoge is None:
#    hoge = "Hello World!"
# ↑↓同じ実行結果
hoge = hoge or "Hello World!"

print(hoge)

# PHPのNull合体演算子に近い
# $hoge = $hoge ?? "Hello World!"

例えばどんなところで役立っているのか

Django(PythonでWebアプリケーションを作るときに使われる、代表的なフレームワーク)でFormのオブジェクトを生成する際は下記のように書くのがお約束です。

form = Form(request.POST or None)

request.POST or None は、 request.POST に値が入っていれば下記のように評価され、

# request.POST に値が入っている場合(Trueと評価される場合)
form = Form(request.POST)

request.POST がFalseと評価される(値が無いなど)場合は下記のように評価されるということです。

# request.POST がFalseと評価される場合(値が入っていないなど)
form = Form(None) # Form() と同義

参考:Logic behind Form(request.POST or None) – StackOverflow

bookmark_border[Python] ヘッダー付きでGETリクエストする

時々書くものの頻繁にではないので忘れてしまうことがありメモ。

TL;DR

GETリクエスト

import requests
# ここでエラーになる場合は
# python -m pip install requests
headers = {
    'Authorization':'Bearer ....'
    # などなど
}
response = requests.get('URL', headers=headers)

レスポンスのbodyを取得

print(response.text)

レスポンスのbodyをJSONオブジェクトとして取得

json() を呼び出す。メソッドであることに注意。

json = response.json()
# 整形して出力
import pprint
pprint.pprint(json)

bookmark_borderpythonコマンドがpython3を見に行くようにする (macOS Monterey)

Macを新しくしてpythonコマンドを使ったら

% python -V
Python 2.7.18

となったのでメモ。

TL;DR

$PATHをいじる、binにエイリアスを張るなど方法はいくつかありますが、.zshrcでpython3コマンドにaliasを張る方法が早そうと判断。

~/.zshrcの編集

vi ~/.zshrc

下記の一文を追加し保存。

alias python=/usr/bin/python3
# Python公式からPythonを別途インストールした場合はこちら
# alias python=/usr/local/bin/python3

ターミナルを開き直すかsourceコマンドで読み直しすることで反映されます。

% source ~/.zshrc
% python -V
Python 3.10.2

めでたし。

bookmark_border[環境構築] TensorFlow+KerasをGPUで動かす[venv]

頻繁にすることではないものの、いざ構築するとなるとやることが多いのでメモ。Pythonの仮想環境はvenvを使います。

1. 構築前の確認事項

グラフィックボードがNVIDIAであること

2022年1月現在、TensorFlowはNVIDIAのGPUドライバだけをサポートしています。

MACなどRadeonのようにNVIDIA以外のGPUの場合は残念ながらTensorFlowを使うことができません。

TensorFlowが求めるGPUドライバ, cuDNN, CUDAのバージョン

TensorFlow公式ページに行き、最新のTensorFlowが求めるcuDNNとCUDAのバージョンを確認します。このバージョンたちにずれがあるとimportに失敗することがあります。

https://www.tensorflow.org/install/source_windows?hl=ja

2. 各種ファイルのダウンロード

CUDA

https://developer.nvidia.com/cuda-toolkit-archive

CUDAはCPUで行う処理をNVIDIAのGPUに行わせる開発環境のことです。TensorFlow公式ページに書いてあったCUDAのバージョンを探し、ダウンロードします。今回の場合11.2系です。

cuDNN(アカウント登録が必要)

https://developer.nvidia.com/rdp/cudnn-archive

登録(ログイン)したらcuDNNのアーカイブページに行き、先ほどTensorFlow公式ページで確認したバージョンのcuDNNをダウンロードします。今回の場合8.1です。

グラボのドライバ(should)

CUDAとcuDNNは大抵バージョンが上がるごとに新しいGPUドライバを求めてくるため、この機会に最新のドライバを入れても良いでしょう。

3. CUDAとcuDNNのインストール

CUDA

インストーラーのため、実行したら画面の指示に従うだけでOKです。

cuDNN

ダウンロードしたzipファイルを展開するとbinなどのフォルダが3つほどあります。

CUDAをインストールしたことによってできた下記のフォルダにそのcudaフォルダの中身を全部移動します。(フォルダとは別にSLAのtxtファイルもありますが、公的文書のため覚書として今回一緒にコピーします)

C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.2
※↑末尾のバージョン番号はインストールしたCUDAのバージョンによって異なります。

4. Pythonのライブラリのインストール

Pythonがインストールされており、パスが通っていること前提です。

pip venv

まずはvenvで仮想環境を作ります。

cd 好きなディレクトリ
python -m venv venv

仮想環境を作ったらactivateしておきます。

venv¥Scripts¥activate

pip install

必要なら tensorflow-gpu=2.6.0 のようにバージョンを指定してください。

pip install tensorflow==2.6.0 keras==2.6.0

バージョン1.15以前はパッケージがtensorflowとtensorflow-gpuに分かれていましたが、それ以降はtensorflowに統一されています。

TensorFlowがGPUを認識できているか確認する

pythonコマンドで対話モードを起動し、下記のように実行します。

参考:https://www.tensorflow.org/guide/gpu?hl=ja

import tensorflow as tf
print("Num GPUs Available: ", len(tf.config.experimental.list_physical_devices('GPU')))

このように1以上の値が出力されていれば認識されています。

Num GPUs Available: 1

下記のコードでも確認できます。

from tensorflow.python.client import device_lib
device_lib.list_local_devices()

いくらか情報が出力され、その中にGPUの名前が出てきていればうまくいっています。

...
physical_device_desc: "device: 0, name: NVIDIA GeForce GTX 1080 Ti, pci bus id: 0000:01:00.0, compute capability: 6.1"

bookmark_border[Keras] Cannot register 2 metrics with the same name で落ちる

Keras(2.7.0) + TensorFlow(2.6.0) を久しぶりに触ったらimportでAlreadyExistsError: Another metric with the same name already exists. と言われ落ちたのでメモ。

E tensorflow/core/lib/monitoring/collection_registry.cc:77] Cannot register 2 metrics with the same name: /tensorflow/api/keras/optimizers
...
...
tensorflow.python.framework.errors_impl.AlreadyExistsError: Another metric with the same name already exists.

TL;DR

TensorFlow2.6 なら Keras2.6 を使うこと。

pip uninstall keras
pip install keras==2.6.0

理由

Keras2.6 + TensorFlow2.7 はバージョンミスマッチのためNG。

KerasのGitHubのIssueを見ると次のような記述あり。

We believe the Keras 2.7.0 release is getting installed by pip when users install Tensorflow, even though Tensorflow 2.7 hasn’t been released to pip yet. The version mismatch (Keras 2.7 + TF 2.6.1) is probably the cause of the error.

(TensorFlow2.7.0はpipで未リリースなのに、pipでTensorFlowをインストールするときKeras2.7.0がインストールされてしまっていると考えられます。エラーはKeras2.7+TensorFlow2.6.1とバージョンが揃っていないことが原因でしょう。)

Another metric with the same name already exists in Keras 2.7.0 #1557

まさに自分のことです。(pip list したら Keras2.7.0+TensorFlow2.6.1 になっていた)

一旦Kerasを2.6.0にしたところ無事動きました。

bookmark_borderAttributeError … has no attribute ‘_TensorLike’

久しぶりにKerasを使ったら落ちたのでメモ。

TL;DR

from keras import ... ではなく from tensorflow.keras import ...

発生するエラー

AttributeError: module ‘tensorflow.python.framework.ops’ has no attribute ‘_TensorLike’

問題のコード

from keras import Sequential
from keras.layers import Conv2D, MaxPooling2D, Activation, Dropout, Flatten, Dense
import tensorflow as tf
model = Sequential()
# ここで落ちる
model.add(Conv2D(64,(3,3), padding='same', input_shape=(192,192,3))
opt = tf.keras.optimizers.rmsprop(lr=0.0001, decay=1e-6)
# ...

修正

# from keras import Sequential
from tensorflow.keras.models import Sequential
# from keras.layers import Conv2D, MaxPooling2D, Activation, Dropout, Flatten, Dense
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Activation, Dropout, Flatten, Dense
import tensorflow as tf
model = Sequential()
model.add(Conv2D(64,(3,3), padding='same', input_shape=(192,192,3))
# opt = tf.keras.optimizers.rmsprop(lr=0.0001, decay=1e-6)
opt = tf.keras.optimizers.RMSprop(lr=0.0001, decay=1e-6)
# ...