はじめに
「Python」学習初手『ゼロから作るDeep Learning』民のためのPython攻略ノートです。『ゼロつく1』学習の補助となるように適宜解説を加えています。本と一緒に読んでください。
本に登場するPython文法や関数について、補足や使い方の確認をしていきます。
この記事は、1章「Python入門」の内容です。本で利用する基本的なPythonの文法などのルールを説明します。
【他の節の内容】
【この節の内容】
1章 Python入門
Pythonの基本的なルール(文法)を説明していきます。
どんな機能があるのかを把握しておくことが重要です。具体的なやり方は何度も戻って確認しながら進めていれば、必要なことから自然と身に付くことでしょう。最初に全てを覚えようとせずに、さらっと確認したら次に進んで、実践の中で反復して使いながら学びましょう(あくまでこんな所までちゃんと読んでいる方へ向けての発言)。
・算術計算
基本的な計算から始めましょう。
足し算は数学記号の通り+
を使います。
数値 + 数値
# 足し算 1 + 1
2
引き算も数学記号の通り-
を使います。
数値 - 数値
# 引き算 2 - 3
-1
掛け算は*
(アスタリスク)を使います。
数値 * 数値
# 掛け算 5 * 20
100
割り算は/
(スラッシュ)を使います。
数値 / 数値
# 割り算 22 / 7
3.142857142857143
累乗の計算には**
(*
を2つ)を使います。
数値 ** 数値
# 累乗 2 ** 10
1024
今何気なく数値を使いましたが、数値にも種類があります(扱いによって区別されます)。次はデータ自体について説明していきます。
・データ型
扱うデータ(の種類)によって利用目的が異なりますね。利用目的に適した機能を持たせるために、データの種類に応じてデータの型を区別して扱われます。
あるデータがどんなデータ型として扱われているのかはtype()
で調べられます。
・整数
まずは、整数型int
(integer:整数)です。整数とは、0から1を足したり引いたりした数です。
type(11)
int
・小数
続いて、浮動小数点型float
(floating-point:浮動小数点)です。要は小数のこと。(メモリの都合上無限に桁を扱える訳ではないなどの注意点はありますが、とりあえず文字通り誤差の範囲です。)
type(22 / 7)
float
ちなみに本で1ではなく1.0のように設定するのは、浮動小数点として認識させるためです。
type(11.0)
float
次からは、数値以外のデータの型になります。
・文字列
文字列str
(string:文字列)です。文字列とは、文字通り文字の連なりのことです。"
(ダブルクォーテーションマーク)あるいは'
(シングルクォーテーションマーク)で挟むことで文字列として認識されます。(どっちが一般的なんだ?)
"好きな文字"
type("Hello!")
str
数字も文字列として扱うことができますが、int
やfloat
として扱うときとは性質が異なります。
type("10")
str
"10" + 10
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-21-f19a135c2b59> in <module>
----> 1 "10" + 10
TypeError: can only concatenate str (not "int") to str
このようにエラーとなり計算できません。その代わりに文字列同士に+
を使うと、次のように2つの文字列を結合することができます。
"10" + "個"
'10個'
・ブーリアン
(本とは前後しますが、)ブーリアン型bool
(boolean:ブール演算子)は、True
(真)とFalse
(偽)の2種類のみからなる型です。論理値と呼んだりもします。(ブール演算子とはand
,or
,not
などのことですが、詳しくは2章で扱います。)
5 > 0
True
0 < -5
False
>, <
は比較演算子といい、x > y
でx
はy
より大きいかを調べます。比較が真(x
が大きい)であればTrue
と出力され、偽(x
が小さい)であればFalse
と出力されます。
条件式の返り値などでよく見かけます。(なので本ではif
の前にあるのでしょう。)
次からは、データをまとめて扱う型について説明していきます。が、その前に変数というものを確認しておきましょう。
・変数
変数とは、データを格納する箱だと言われます(いや箱の例えは適切ではないという論争も存在します。私は初学者にはExcelでいうところの(名前を自由に決められる)セルのことだとよく説明します)。
変数を作成するには=
を使います。=
を等式の数学記号と思うと理解に苦しむかもしれません。Pythonの=
は代入記号だと思いましょう。変数を作ることを代入するや定義するとも言います。(ちなみにPythonの等式記号は==
(=
を2つ)です。)
変数名 = データやデータを生成する処理
# 変数を作成 A1 = 11 print(A1)
11
変数の中身はprint(変数)
で表示できます。
変数同士で計算もできます。
B1 = 21
A1 + B1
32
変数に再代入したり、変数の計算結果を新たな変数に代入することもできます。
A1 = 1 C1 = A1 + B1 print(C1)
22
type(変数)
で、変数(の中のデータ)のデータ型を確認できます。
type(C1)
int
変数名には、アルファベットと数字と_
(アンダースコア)が使えます。ただし1文字目に数字を使うことはできません。また(次の次くらいで出てくる)予約語という特別な意味(役割)を持つ語を(そのまま)変数名にすることはできません。
同じ文字でも大文字と小文字は別の文字として認識されます。
def = "define"
File "<ipython-input-76-655c74b574ee>", line 1
def = "define"
^
SyntaxError: invalid syntax
予約語を変数名にしようとすると、このようにエラーとなります。
大事なのは「エラーにならないように全ての予約語を覚えよう!」ではなく、エラーが出たときに「あ、何か変数名にできないものあったなぁ。名前を変えてみよう」と思えればいいということです(勿論他のことがエラーの原因かもしれません)。気楽にいこう(頭を使うのはここではない)!(もっともJupyterを使ってるなら緑色で表示されるので気付けると思いますが。)
変数名について一歩進んだ注意点として、名付け方があります。
複雑なシステムを組もうとすると、様々な処理の中でたくさんの変数を使うことになります。それぞれが何を意図したものか一目で分かるように、その働きを適切に表す名前を付けることは非常に重要です(これがかなりムズい)。
また、役割を示すために複数の単語を変数名に使いたいことがあります。例えば変数名をトピックモデル(Topic Models)としたいとき、2つの単語をアンダースコアで区切ってtopic_models
とするか、大文字で単語の区切りを示してTopicModels
とする方法があります。変数名や関数なら前者、クラス名には後者とするのが一般的なお約束です(詳しくはPEP8を調べてください)。
変数にもデータの型があります。利用目的に応じてデータ型を使い分けます。次からは変数のデータ型と作成方法を紹介していきます。(ただしクラスについては触れないことにします。)。
・リスト
リストlist
は、複数のデータを格納する基本的な型(方法)です。リストを作るには、要素全体を[]
で囲み、要素ごとは,
で区切ります。
変数名 = [要素0, 要素1, 要素2]
# リストを作成 lt = [0, 1, 2] print(type(lt)) print(lt)
<class 'list'>
[0, 1, 2]
数値以外のデータを扱うこともできます。
# (文字列データの)リストを作成 lt_str = ["berry", "cute"] print(type(lt_str)) print(lt_str)
<class 'list'>
['berry', 'cute']
変数の後に[添字]
を付けることで、リストに含まれている要素の中から必要な要素のみにアクセスできます。またこれを添字と呼びます。
(リスト型の)変数名[(要素の位置を示す)数値]
print(lt[0]) print(lt_str[1])
0
cute
重要なことなのでここでさらっと書くことではないのですが、Pythonでは最初の要素を0番目と表現します。そして最初の次の要素が1番目になります。注意してください。(何言ってんだよ、君が1番さ!(Pythonジョーク()))
・ディクショナリ
ディクショナリdict
は、キーとデータをペアとして格納する型です。単語で検索して対応する意味を引ける辞書という訳ですね。要素全体を{}
で囲み、キーとデータを:
(コロン)で結び、要素(ペア)ごとは,
で区切ります。
変数名 = {'key0':'データ0', 'key1':'データ1', 'key2':'データ2'}
# ディクショナリを作成 hello_dic = {'masaki':'morning', 'rin':'angerme', 'karin':'juice'} print(type(hello_dic)) print(hello_dic)
<class 'dict'>
{'masaki': 'morning', 'rin': 'angerme', 'karin': 'juice'}
変数名の後ろに[キー]
を付ける(指定する)と、対応するデータが返ってきます。
(ディクショナリ型の)変数名['(必要なデータの)キー']
# 要素にアクセス hello_dic['karin']
'juice'
また、変数名の後ろに[新しいキー名]
と指定し、対応するデータを代入することで、新しい要素を追加できます。
変数名['key3'] = `データ3`
# 要素を追加 hello_dic['honoka'] = 'beyooooonds' print(hello_dic)
{'masaki': 'morning', 'rin': 'angerme', 'karin': 'juice', 'honoka': 'beyooooonds'}
ここで紹介した以外の機能もたくさんあります。本で利用するタイミングで適宜解説を加えます。また他にもデータ型はありますが、本では利用しないため紹介するのは止めておきます。
・制御構文
プログラムの処理を制御する特別な機能についていくつか説明していきます。(ここで扱うものが予約語の一部でもあります。)
それぞれ制御構文の最初の行の末尾に:
を入れる必要があります。またそれに続く処理の部分に関しては、行の頭に␣␣␣␣
(半角スペース4つ)入れる必要があります。これをインテンドと呼びます。インテンドされている部分が、これから紹介する構文の範囲だと認識されます。(勝手に入れてくれてると思いますが)
・if文
if
を使って、条件分岐を行えます。
if
の後にTrue
かFalse
の値となる条件式やリストなどを指定し、行末を:
にします。次の行からは条件を満たす場合に行う処理を書いていきます。このとき、行の頭にインテンドを入れる必要があります。インテンドされている処理がif
文の範囲として認識され実行されます。
if 条件式など: (条件を満たすとき行う)処理
# 身長を入力 height = 130 # 条件分岐 if height >= 120: print("ご乗車可能です!")
ご乗車可能です!
x >= y
はx
がy
以上であるかを調べる比較演算子です。
height
(身長)が120
以上なので、条件を満たしています。よってprint("ご乗車可能です!")
が実行され、"ご乗車可能です!"
という文字列が表示されました。(無事ジェットコースターにでも乗れたのでしょう。)
では、身長が120未満だった場合はどうしましょう?
条件をを満たさなかった場合の処理を加えるには、if
の処理の後に続けてelse
を使います。(これはif
で指定した条件を満たしたときに実行したいことではないので、)行頭にインテンドを入れずにelse
と:
を書きます。そして次の行にif
文と同じく実行したい処理を書いていきます。
if 条件式など: (条件を満たすとき行う)処理 else: (条件を満たさないとき行う)処理
if
で条件を満たさなかった全てのパターンで実行する処理なので、else
には条件が要りません。
# 身長を入力 height = 110 # 条件分岐 if height >= 120: # 条件を満たす場合 print("ご乗車可能です!") else: # 条件を満たさない場合 print("カルシウム摂りな!")
カルシウム摂りな!
さらに条件を増やしたい場合は、elif
(else if)を使います。条件の指定方法などはif
と同じです。
if 条件0: (条件0を満たすとき行う)処理 elif 条件1: (条件1を満たすとき行う)処理 else: (全ての条件を満たさないとき行う)処理
# 身長を入力 height = 210 # 条件分岐 if height > 200: # 条件0を満たす場合 print("頭ぶつかるからごめんな…") elif height >= 120: # 条件1を満たす場合 print("ご乗車可能です!") else: # 条件を満たさない場合 print("カルシウム摂りな!")
頭ぶつかるからごめんな…
elif
を使えば複数の条件を加えることができます。ただし条件を増やすときには、その順番に注意する必要があります。
この例では新しい条件を最初に加えましたが、これを間に加えるとどうなるでしょうか?きっと痛い思いをさせてしまうのでしょうね…
・for文
for
とin
を使って、ループ処理を行えます。
for
から始まる行末に:
を書きます。そして、繰り返し行う処理についてはインテンドを入れる必要があります。
for i in リストなど: (繰り返し行う)処理
# 値が0の変数を用意 x = 0 # ループ処理 for i in [1, 2, 3]: # リストの要素を順番にxに足す x = x + i print(x)
6
まずは、リストに含まれる要素が1つi
に代入されます。そして、インテンドされている処理を実行します。その処理を全て行うと、またリストから次の要素を取り出してi
に代入し、指定された処理を実行します。つまり、リストに含まれる要素数回繰り返し(同じ)処理を行うことになります。
i
に異なる値を与えて添字などに利用することで、複数のデータに対して順番に同じ処理を繰り返すことができます。(実例の方がイメージしやすいと思うので、そのときまで保留していてください。)
i
以外の文字列を使うことも可能です。
・関数定義
def
(define:定義する)を使って、オリジナルの関数を定義(作成)出来ます。
def
の行末に:
を付ける必要があります。また定義した関数を実行したときに行う処理部分にはインテンドが必要です。
def オリジナル関数名():
(オリジナル関数として)実行する処理
# "Hello World!"と返す関数を定義 def hello(): print("Hello World!")
これで新しい関数hello()
を作成できました。では使ってみましょう!
hello()
Hello World!
hello()
と打つだけで、Hello World!
と表示させることができた!でも世界以外にも挨拶したくもなるでしょう。そんな場合には引数を使います。
def 関数名(引数名):
(オリジナル関数として)実行する関数(引数名)
# 引数に渡した文字列に対して挨拶する関数を定義 def hello(arg): print("Hello " + arg + "!")
関数の利用時に指定した引数を"Hello "と"!"で挟んで返すように関数を定義しました。
hello("cat")
Hello cat!
猫ちゃんこんにちは!
よく行う処理をオリジナル関数としてまとめておくと、コード全体を見直す時に分かりやすくなったりやメンテが楽になったりします。(今後複雑なことをしていくので、その内分かりますよ。)
・クラス
クラスの説明をします。ただし中々複雑な概念であるため、ここでは最小限に留めておきます。それでも、4章まで登場しない概念なので、それまで飛ばすことをお勧めします。
行いたい分析があったとします。その分析には、変数や計算やその他処理が必要ですよね。それらを予め利用しやすい形にまとめておくと、実装していく上で便利そうです(なんです)。そのようにまとめたものをクラスと言います。(なのでクラスはよく設計図に例えられます。)
目的の分析を行う際には、定義したクラスを使ってインスタンス(instance:実例・実体)を作成します。作成したインスタンスは、クラス内で定義したメソッド(method:方法)を利用することができます。
さて、新しい(そしてイメージしにくい)単語が次々と出てきましたね。1つずつ確認していきましょう。
まずはclass
を使って、クラスを定義します。クラスの一部として定義される関数をメソッドと呼びます。メソッドの定義は関数定義と基本的に同じです。ただし第1引数をself
とします。self
が何か気になりますが、クラスを利用してみるまで保留していてください。
class クラス名: def メソッド名(self): (メソッドを利用するときに)行う処理
これがクラスの基本構造になります。
続いて、クラスの使い方を説明します。
定義したクラスを使うには、クラスを適用させたい変数に対してクラス名に()
を付けて代入します。クラスを適用した変数をインスタンスと呼びます。設計図(クラス)に従い作成された実例・実体(インスタンス)ということです。
インスタンス名 = クラス名()
このように、変数にクラスを反映する(インスタンスを作成する)ことをインスタンス化すると言います。
インスタンス(クラスが反映された変数)は、クラスで定義されているメソッド(そのインスタンスだけが使える関数)を使うことができます。インスタンス名(変数名)に.
を付けて、使用するメソッド名(関数名)を指定します。
インスタンス名.メソッド名()
さて、クラスの定義の時点ではこのインスタンス名(インスタンス自身)はまだ何か分からないものでした。そこでインスタンス自身(仮)のことをself
として定義していました!
では実際にクラスを作ってみましょう。
"Hello!"と返すメソッドを持つクラスを定義します。
# クラスを定義 class SayHello: # メソッドを定義 def say(self): print("Hello!")
"Hello!"
を返すメソッドsay()
を持つクラスSayHello
を作成しました。ではSayHello
クラスを用いて、変数をインスタンス化してみます。
# インスタンス化 obj = SayHello() # クラスメソッドを使用 obj.say()
Hello!
素直にsay()
という関数を作った方がいい気がしますね。実際単純な処理だと関数定義をした方が良いでしょう(なので3章まではクラスが登場しません)。
では次に、引数をとる(ほんの少し)複雑なクラスを定義する場合を説明します。
主な違いは、def __init__
でインスタンス変数を定義する点です。initは、initial(:初期値)あるいはinitialize(:初期化)を表します(どっち?)。
class クラス名: def __init__(self, 引数名): self.引数名 = 引数名 def メソッド名(self): (引数を使う)処理
self.引数名
がインスタンス変数です。このインスタンス変数は、好きに取り出すことができます。
変数名.引数名
またここでいう引数とは、インスタンス化する際に渡される引数のことです。(メソッドを使用するときにとる引数を定義することもできます。)
変数名 = クラス名(引数)
実際に組んで確認しましょう(クラスについてはとりあえずこれで最後です)!Hello [引数に指定した文字列]!
と返すメソッドを持つクラスを作成します。
# クラスを定義 class SayHello: # インスタンス変数を定義 def __init__(self, arg): self.arg = arg # 引数に指定した文字列をそのままインスタンス変数とする # メソッドを定義 def say(self): print("Hello " + self.arg + "!") # "Hello!"と引数に指定した文字列を結合して表示する # インスタンス化 obj = SayHello("Python")
これでクラスの作成とインスタンス化ができました。
インスタンス化する際に指定する引数(ここでは"Python"
)は、(定義の段階では2つ目の引数)arg
引数に渡されます。self
はインスタンス自身(ここではobj
)のことなので、第1引数としては機能しません。
インスタンス変数を確認します。
# インスタンス変数を呼び出す
obj.arg
'Python'
引数として渡した"Python"
がインスタンス変数として保存されています。
メソッドも確認します。
# メソッドを使用
obj.say()
Hello Python!
意図した通りに処理されていますね。
お疲れ様でした!以上がクラスの中心的な機能になります。もうちょっと付け足したい事柄もありますが、それは【実装ノート】の方で適宜補足します。
次からは、(外部)ライブラリの説明をします。
その前にライブラリとは、特定の目的に応じたクラスや関数をまとめたものです。元から組み込まれているものを標準ライブラリと呼び、個別にインストールした後に利用できるものを外部ライブラリと呼びます。(余談ですが、新たなライブラリが開発されることでも言語が発展していきます。)
本で主に利用する2つのライブラリを確認していきます。
・NumPy
NumPy
とは、計算処理に便利な外部ライブラリです。NumPy
の説明の前に、まずはライブラリの読み込み方法を説明します。
・ライブラリのインポート
import
を使ってライブラリを読み込みます。ライブラリのインストールについては扱いません(Anaconda前提ですので、、、私がそうだから)ので、必要であれば調べてください(すみません)。
import ライブラリ名
# ライブラリを読み込む import numpy
これでNumPy
の関数を利用することができます。
ライブラリの関数を利用するには、ライブラリに.
を付けてライブラリに含まれる関数を指定します。
ライブラリ名.関数名(引数)
一度ライブラリを読み込めばPythonを閉じるまで利用できます(何度もインポートする必要はありません)。Pythonを閉じたらもう一度読み込む必要があります。
NumPy
に含まれるsum()
関数を使ってみます。引数に渡した値を全て足す関数です。
# NumPyの関数を使用 numpy.sum([1, 2, 3])
6
ライブラリ名を毎回打ち込むのはメンドイよね。ということでas
を使って省略形に置き換えることができます。
# ライブラリを読み込む import ライブラリ名 as 省略形 # 関数を使用 省略形.関数名(引数)
省略形は別になんでもいいです(より長いものでも可)。ただ、当然誰が見ても理解できるようにしておくのが吉ですね。一般的に用いられる省略形があります。NumPy
ならnp
、次に出てくるMatplotlib
ならplt
です。
# NumPyを読み込み import numpy as np # NumPyの関数を使用 np.sum([1, 2, 3])
6
・NumPy関数(1)
np.sum()
は、引数の値の和をとる関数でした。他にもNumPy
は数値処理を行う関数があります。しかしここで、どんな関数があるのかを網羅的に書いてもしょうがないので、、、今後出てくるnp.hoge()
が全部それです。(hogeやfooというのは「○○」や「ほにゃらら」のような単語です。野良記事で見ることでしょう(使ってみたかった!)。)
もう1つ(1.6節で初登場する)np.arange()
を紹介します。(本で初登場する関数は【Pythonノート】の各章で適宜紹介します。)
・np.arange()
第1引数
以上第2引数
未満の数値列を作り、NumPy配列で返します。
np.arange(0, 10)
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
第3引数
に間隔を指定することもできます。
np.arange(0, 10, 2)
array([0, 2, 4, 6, 8])
・NumPy配列
NumPy関数の他に、NumPy配列にもとてもお世話になります。NumPy配列ndarray
もデータ型の1つです。(勘のいい方は薄々気付いているかもしれませんが、データ型というのはクラスのことだったりします。しかし本を進めるにあたってそう認識することの恩恵はあまりないため、ノートでは触れないことにします。本ではメソッドと呼んでいますが、こちらでは(頑なに)NumPy関数で通します。)
NumPy配列を作成するには、np.array()
を使います。また、他のNumPy関数の出力がNumPy配列であることもあります。
変数名 = np.array(リスト)
# NumPy配列を作成 dat = np.array([1.0, 2.0, 3.0]) print(dat)
[1. 2. 3.]
type(dat)
numpy.ndarray
表示をいい感じにしてくれているのもNumPy配列の機能の1つです。
またリストを入れ子にすることで、次元を増やすことができます。2次元配列の場合は次のようにリストの中にリストを含めます。(2次元配列に対して上の例を1次元配列と呼びます。詳しくは3.3節で取り上げます。)
変数名 = np.array([[リスト0], [リスト1]])
# NumPy配列形式の2次元配列を作成 dat2 = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]]) print(dat2)
[[0 1 2]
[3 4 5]
[6 7 8]]
type(dat2)
numpy.ndarray
・Matplotlib(1)
2つ目はグラフを描くためのライブラリであるMatplotlib
です。グラフの作図に使う関数が多数あります。
matplotlib
ライブラリのpyplot
モジュール(この言葉は覚えなくて大丈夫)を利用します。matplotlib.pyplot
をplt
として読み込んで利用します。
# Matplotlibを読み込む import matplotlib.pyplot as plt
早速$y = 2 x + 3$のグラフを描いてみましょう。
# x軸の値を生成 x = np.arange(0, 10) print(x) # y軸の値を計算 y = 2 * x + 3 print(y)
[0 1 2 3 4 5 6 7 8 9]
[ 3 5 7 9 11 13 15 17 19 21]
グラフにする値を、plt.plot()
に指定します。第1引数がx軸で、第2引数がy軸になります。
値を指定できたら、plt.show()
で描画します。
# 作図 plt.plot(x, y) # x軸とy軸の値を指定 plt.show() # 描画
例えばグラフにタイトルも表示したければ、グラフタイトルを指定する関数plt.title()
を使います。第1引数にタイトルとして表示する文字列を指定します。また他にもフォントサイズを指定する引数fontsize
などがあります。
# 作図 plt.plot(x, y) # x軸とy軸の値を指定 plt.title("Graph Title", fontsize = 20) # タイトルを指定 plt.show() # 描画
このように、グラフに表示したいものをそれに対応する関数を使って描き加えることができます。
以上で1章の内容は終わりです。以降はここで紹介したPythonの基本的な文法に従って、ニューラルネットワークを実装していきます。
参考文献
おわりに
これくらいのレベル感で最後まで書いていく予定です。今現在3章が書き終わったところです。
最後までお付き合いいただけたら嬉しいです。
ちなみに私は、1か月前にこの本で初めてPythonに触れました。プログラミングはR経験が2年ほどです。確率分布とはから1年ほど機械学習の勉強していますが、深層学習はこれが初めてです。十分かどうかは分かりませんが、書いているのはそんなレベルの人です。
だからこそ書けることもあるという気持ちと、いやこれ自体が自分の勉強になるからという気持ちで書いています。内容に間違い等あるかと思います。見付けたら全て指摘していただけるととても助かります。よろしくお願いします。
if
とfor
は制御構文でいいと思うのですが、def
やclass
も制御構文にまとめてしまっていいのでしょうか?予約語でまとめるのも違うし、、、
あと文字列のときに"
と'
どっちを使うのが一般的なのかも知りたいです。本では両方使ってるよーな??
というレベル感です!あんまり大型書店にも行けない今日この頃なので、お薦めの入門書なぞあれば教えてほしいです。
【次節の内容】