Lesson 9 条件分岐 ― Python基礎文法入門機械学習&ディープラーニング入門(Python編)

Python言語の文法を、コードを書く流れに沿って説明していく連載。今回は制御構文のうち、条件分岐について説明する。ロジックや処理フローを定義するための大事な文法である。

» 2019年04月08日 05時00分 公開
[一色政彦デジタルアドバンテージ]

この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。

「機械学習&ディープラーニング入門(Python編)」のインデックス

連載目次

ご注意:本記事は、@IT/Deep Insider編集部(デジタルアドバンテージ社)が「deepinsider.jp」というサイトから、内容を改変することなく、そのまま「@IT」へと転載したものです。このため用字用語の統一ルールなどは@ITのそれとは一致しません。あらかじめご了承ください。

 前回は「関数の定義方法」について紹介した。今回は、プログラムの処理フローを作るのに欠かせない「制御構文(条件分岐)」について説明する。脚注や図、コードリストの番号は前回からの続き番号としている。

 本連載は、実際にライブラリ「TensorFlow」でディープラーニングのコードを書く流れに沿って、具体的にはLesson 1で掲載した図1-a/b/c/dのサンプルコードの順で、基礎文法が学んでいけるように目次を構成している。今回は、図1-b/d内の一部コードを取り上げる。

TensorFlowの公式チュートリアルのサンプルコード 図1-b【再掲】 TensorFlowの公式チュートリアルのサンプルコード(2)

TensorFlowの公式チュートリアルのサンプルコード 図1-d【再掲】 TensorFlowの公式チュートリアルのサンプルコード(4)

 今回、本稿で説明するのは図1-b/d【再掲】における赤枠内のコードのみとなる。

 なお、本稿で示すサンプルコードの実行環境については、Lesson 1を一読してほしい。

 Lesson 1でも示したように、本連載のすべてのサンプルコードは、下記のリンク先で実行もしくは参照できる。


Google Colabで実行する
GitHubでソースコードを見る

Python言語の基礎文法

 プログラミングは、ロジック(=思考の道筋、論理)や処理フロー(=流れ)の連続で形作られる。そこで必要となるのが、「もし□□であれば、○○をする。そうでなければ××をする」といった条件分岐や、「データの最後まで、順番に1件ずつ○○をする」といったループ処理(=繰り返し処理)、といったロジック/フローを制御するための構文である。

 そこで、今回は条件分岐を、次回Lesson 10ではループ処理を説明する。

条件分岐

 「もし□□であれば」から想像が付くように、条件分岐を実現するのは、ifキーワードを使った構文である。図1-bの中ほどに、実際にそのif文がある。それを抜き出したのがリスト12-1である。

predicted_label = '猫'
true_label = '犬'
# 上の2行は下記コードの実行に必要な仮のコード

if predicted_label == true_label:
  color = 'blue'
else:
  color = 'red'

color  # 'red'と出力される

リスト12-1 条件分岐を行うコード例

 このif文コードの構造をイメージにしたのが図13-1である。

条件分岐、のイメージ 図13-1 条件分岐、のイメージ

 基本的な書き方は、前回Lesson 08で説明した関数定義と似ているのが分かるだろう。インデントについて、関数では「スコープ」とも書いたが、ここでは「ブロック」と表現している。条件分岐の説明を優先して、両者の違いについては次節で述べることにする。

 関数定義であればdefだったところが、条件分岐では「もし□□であれば」を意味するifに代わり、「ブロックの開始」を意味するコロン:がやはり使われている。ブロックにはインデントを付けて、条件がTrue)であるときに実行する処理内容が記載されている。

 続けて、インデントを解除してブロックが終了された後、「そうでなければ」を意味するelseキーワードとコロン:が使われている。再度、インデントを付けて、条件がFalse)であるときに実行する処理が記載されている。

 先ほども説明したが、Pythonにおいてはインデントがブロック(つまり範囲)を決めるので、インデントをきれいに整えるのに細心の注意を払う必要がある*6

*6 ちなみに、多くの他の言語(JavaScriptやC言語など)では、見やすさのためにインデントは付けるものの、それによってブロックが決まる仕様ではないので、インデントがずれても問題にはならない。しかしPythonでは問題が生じる。つまり、インデントの取り扱いに柔軟性がない。ただし「柔軟性がない」ことがデメリットというわけではなく、「誰が書いても見やすいコードになるメリットがある」と考える人もいる。この点が「Pythonが好きか嫌いか」を分ける大きな要因の一つにもなっている。最近では、「Pythonは数学関連ライブラリが充実しているメリットが大きい」ということで、好き嫌いは別にして、Pythonの利用者数は着実に増えている。


 条件の部分はpredicted_label == true_labelというコードになっている。これは、「predicted_label(予測ラベル)がtrue_label(教師ラベル)と==(イコール)であるか?」という(expression)になっている。この式は、TrueFalseのbool値(真偽値)を返す。それがTrueであればif文の配下ブロックにあるcolor = 'blue'(=変数color'blue'という値を代入)が実行され、Falseであればelse文の配下ブロックにあるcolor = 'red'が実行される。

 ==半角のイコールが2つ)のように、左辺 == 右辺という式で、左辺と右辺を比較する記号を、比較演算子と呼ぶ。比較演算子は表2のものが用意されている。

比較演算子 記述例 意味
== a == b bが、aに等しい
!= a != b bが、aに等しくない
> a > b bより、aが大きい
>= a >= b bより、aが大きいか等しい
< a < b bより、aが小さい
<= a <= b bより、aが小さいか等しい
表2 条件で使える比較演算子

 先ほどの例はシンプルな2分岐の条件判定だった。しかし、「もし□□であれば(if)」「もしくは◇◇であれば」「もしくは☆☆であれば」「それら以外であれば(else)」というように、3つ以上の分岐をしたい場合もあるかもしれない。このような場合には、elif文を間に追加すればよい。例えばリスト12-2のようになる(イメージは先ほどとほぼ同じなので割愛)。

predicted_label = '猫'  # この行は下記コードの実行に必要な仮のコード

if predicted_label == '犬':
  color = 'blue'
elif predicted_label == '猫':
  color = 'green'
elif predicted_label == '馬':
  color = 'yellow'
else:
  color = 'red'

color  # 'green'と出力される

リスト12-2 3つ以上の条件分岐を行うコード例

 また、elseを加えずに条件分岐を作ることもできる。リスト12-3がその例だ。ここではelif文を加えているが、これを無くして、if文単独の条件分岐にすることも可能だ。

predicted_label = '猫'  # この行は下記コードの実行に必要な仮のコード

color = 'white'

if predicted_label == '犬':
  color = 'blue'
elif predicted_label == '羊':
  color = 'pink'

color  # 'white'と出力される

リスト12-3 else文が含まれない条件分岐のコード例

 ちなみにPython以外のプログラミング言語をかじったことがあれば、switch文による条件分岐はないのか、という疑問があるかもしれない。Pythonにはswitch文に相当する構文はないので、elif文を駆使して、3つ以上の条件分岐を行う必要がある。

ブロックとスコープの違い

 さて、ここまで説明を保留してきたブロックとスコープだが、必要な構文の説明が終わったので、ここらで詳しく説明しておこう。

 関数の場合は、「ブロック」であり「スコープ」でもあると説明した。このスコープとは、関数(=def文のは配下の)とモジュールにおいて適用される概念である。ブロックblock)が「開始〜終了の範囲」を表すのに対し、スコープscope)は「変数などにアクセスできる範囲」を表す。

 if文はブロックを明示するが、スコープではない。例えばリスト12-4で、if文による条件分岐の配下にあるブロックでcolor = 'blue'と変数の宣言と代入が行われているが、最下行にcolorと記載されており、if文のブロックの外から、変数colorにアクセスしている。これは、変数colorがモジュール内の「全体」を意味するグローバルスコープで生成されているためだ。グローバルスコープの変数は、グローバル変数とも呼ばれる。なお、ここで言うモジュールとはPythonファイル(.pyファイル)のことであり、Google ColabやJupyter Notebookにおいてはノートブック(.ipynbファイル)のことである。

predicted_label = 100  # この行は下記コードの実行に必要な仮のコード

if predicted_label == 100:
  animal = 'イヌ'  # グローバルスコープでの変数宣言になる

animal  # 'イヌ'と出力される

リスト12-4 if文内の変数宣言はグローバルスコープで宣言されている

 一方、リスト12-5のようにdef文による関数の配下にあるブロックでsize = 10と変数の宣言と代入を行った場合、この変数sizeには関数の外部からはアクセスできない。これは、変数sizeが関数のブロック内のみのローカルスコープで生成されているためだ。ローカルスコープの変数は、ローカル変数とも呼ばれる。

def some_function():
  size = 10  # ローカルスコープでの変数宣言になる

some_function()  # 関数を呼び出す
size  # 変数は定義されてないとしてNameError(名前のエラー)になる

リスト12-5 関数定義内の変数宣言はローカルスコープで宣言されている

 図13-2では、グローバルスコープとローカルスコープの違いを比較している。

グローバルスコープとローカルスコープ 図13-2 グローバルスコープとローカルスコープ

 要するに、関数内(もしくはクラスのメソッド内)で宣言した変数は、関数(やメソッド)の外では使えない。関数以外で宣言した変数は、同一ファイル内であれば使える、と覚えておけばよい。

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。