機械学習のためのPython入門

はじめに

本記事は、弊社で開催しているセミナーの予習記事として位置づけています。
そのため、機械学習を学ぶことを前提として必要な機能のみを最短で紹介してきます。
こちらを学んでいただき、Pythonの文法やJupyter Notebookの使い方を把握していただければ、セミナーの受講が非常にスムーズに進めますので、ぜひしっかりと予習していただけますと幸いです。

また、こちらの記事は一般向けにも公開しており、ぜひこれから機械学習を学ぶ人の足がかりとなれば幸いです。
こちらの記事で弊社(株式会社キカガク)に興味を持っていただけた方は、ぜひセミナーでお待ちしております。

なぜPythonを使うの?

データ解析からアプリケーション実装がシームレスに行える

Pythonはデータ解析でよく使用される言語ですが、実際は初期のFacebookをはじめとしたWebアプリケーション制作にもよく使われています。
他言語も含めた位置づけはこのようになります。

python.png

もちろんRubyやPHPでも解析ができたりするのですが、NumpyというライブラリがあるPythonが解析においては抜きん出ているのは間違いありません。
解析だけの観点では、MATLABやRも強力な線形代数演算をサポートするライブラリがあるのですが、Webアプリケーションへ落とし込むとなると、なかなか扱いづらかったりします。
そんな解析とWebアプリケーションの機能を両方共備えていて、かつ初心者にも扱いやすいのがPythonです。

Pythonはライブラリが豊富

さらに、画像処理や音声処理、自然言語処理のどの分野においても、スタンダードに近いライブラリが存在しており、リファレンスも豊富なため、機械学習とPythonの相性は非常に良いといえます。

PCにPythonを実行できる環境を構築しよう

PCへPythonの実行環境を構築してみましょう。
環境構築に関しては、こちらで詳細に解説していますので、お持ちの環境に合わせて下記の記事をご覧いただきながら、環境を構築をしてみてください。

Windowsの方

【決定版】WindowsでPythonを使って『機械学習』を学ぶための環境構築

Macの方

【決定版】MacでPythonを使って『機械学習』を学ぶための環境構築

Pythonを使ってみよう

Jupyter Notebook、それはデータ解析界の救世主

Pythonでは、以下の3つの方法で実行することができます。

1.ターミナルで対話モードにより実行

ターミナル(コマンドプロンプト、Windows PowerShell)から python3(もしくはpython)と入力して、インタラクティブ(対話)モードとして実行

インタラクティブモードではすぐにエラーが表示されたりと、デバッグが容易といったメリットがあります。
それに対し、前に戻って編集できなかったり、まとめて実行できなかったりと、再利用性は低いため、お試し用に使う程度です。

2.エディター(メモ帳)にスクリプトを書き、実行

sample.pyというファイルの中に、以下のスクリプトを記述し、保存しておきます。

そして、これを実行します。

こちらの方法では、まとめて記述できるため、再利用性が高まりますが、その分、デバッグが容易ではなく、ソースコードの分量が多くなってきた際に、どんどん保守性が低くなっていきます。

3.Jupyter Notebookで実行

Jupyter Notebookはターミナル(コマンドプロンプト、Windows Powershell)でjupyter notebookとコマンドを打つと実行されます。

Jupyter Notebookはブラウザ上で操作を行うため、OSの違いをほとんど気にすることなく実行することができます。
また、もう一点すごいこととして、ローカルとリモートの違いも気にせずに実行できるため、クラウド上にある高性能なGPU搭載のマシンを手元にあるかのように実行できます。

「New」から新しいファイルを作成しましょう。

Jupyter Notebookではプログラムを書き、「Shift+Enter」で実行できます。
普通に「Enter」を押すと、改行になります。

Jupyter Notebookでは、
「1.ターミナルで対話モードにより実行」で紹介した方法のインタラクティブに実行でき、デバッグを容易にしているというメリットと、
「2.エディター(メモ帳)にスクリプトを書き、実行」のまとめて実行する再利用性の高さ
の2つを両立しています。

特に、データ解析ではデバッグ作業が大半を占めるため、デバッグを容易にできるというメリットは非常に大きなポイントとなります。

Pythonを速習

変数

Python含めプログラミング言語では変数と呼ばれる数値を入れておくための箱を準備しておきます。
変数には大きくわけて、数値文字があります。

変数に数値や文字を渡すことを代入と呼び、「変数 = 数値 or 文字」のように=が代入のための記号になります。
この=は数学的な等しいとは全く異なり、左側の変数に、右側の数値や文字を代入するという意味のため、間違えないように気をつけましょう。

数値の変数

これは a という変数に 1 を代入していることになります。

変数の中身を確認したい時は print(a) のように print というコマンドを使用することを覚えておきましょう。
printは非常によく使います。

いかがでしょうか。
1と表示されればOKです。

Jupyter Notebookでは下記のように表示されて、すぐに結果を確認することができます。

※ 数値には種類があるので注意

コンピュータの内部的な処理の話であるため、最初はあまり気にすることはないのですが、int型と呼ばれる整数とfloat型と呼ばれる実数(少数を含んだ数値)を扱うための数値型の2種類があります。

 

Pythonでは、整数を代入すればint、実数を代入すればfloatと自動的に判定してくれるため、最初はあまり気にする必要はありません。
Chainerでは、この数値型の変数の取り扱いに制約の制約があるため、また先で出てくると覚えておきましょう。

なお、現在宣言されている数値がintfloatといった方を知りたい時は、type()を使えばOKです。

文字の変数

文字の代入も数値と同じように=を使うだけです。
ただし、文字を扱う場合は、' '(シングルクォーテーション)もしくは " "(ダブルクォーテーション)のどちらかで文字を囲んで上げる必要があります。
この2つはどちらでも機能的には同じであるため、好きな方をお使いください。

これも表示してみましょう。

文字列は足し算により、文字列の結合ができます。

こちらはよく使う処理ですので、ぜひ覚えておいてください。

これで変数の代入はざっくりと完了です。

四則演算

足し算は+、引き算は-、掛け算は*、割り算は/で表現します。
また、べき乗は**です。

基本構文

比較演算

大小の比較は <(もしくは>)、等しい場合は==、等しくない場合は!=、下記のように表現します。

エスケープシーケンス

通常の文字列では表せない特殊な文字や機能を、規定された特別な文字の並びにより表したもの
よく使うものとして、\n(もしくは ¥n)によって改行を表示できます。

また、自然言語処理の際にMeCabを使用するのですが、こちらでは改行以外にタブも扱うため、タブが\t(もしくは¥t)で表現できることを覚えておきましょう。

コメントアウト

コメントアウトはプログラムとしては意味を持たないものですが、他の人にプログラムの機能を伝えるためによく使うため、覚えておきましょう。

コメントアウトは command + /(もしくはcontrol + /)で簡単に切り替えることができるため、覚えておくと便利です。

複数の変数を扱おう

リスト

変数を[]で囲んで並べたもの。
それぞれの変数のことを要素と呼びます。

まず、リストとして定義してみましょう。

そして、この一番左側の要素にアクセスするには 0から要素番号が始まっています。

つぎに、リストから部分的に取り出してみましょう。

:(コロン)を使うことで部分的な要素を取り出すことができます。
ここで多少ややこしいのですが、0から3と指定していますが、これは「要素番号が0番目から3番目のひとつ手前までの要素を抜き出す」という仕様となっています。
なぜ、このようなややこしい仕様となっているのでしょうか。

実は、一番最初の要素である0は省略することができ、以下のように記述できます。

このように記述すると、「先頭から3つを取り出す」と非常に直感的に扱うことが出来るためです。

そして、「3番目から最後まで」は以下のように記述できます。

そして、よく使うのですが、「全て」は以下のように記述します。

こちらだけでは、numbersと表示することと全く変わりませんが、この記述方法は2次元以上の多次元配列となった際に効果を発揮します。
「matrixという多次元配列の特定列(0)の全ての行」といったいったときには matrix[:, 0]のように記述(こちらはNumpyの扱い方ですが)することがありますので覚えておきましょう。

リストは数値以外にも、文字列も扱えます。

また、リストでは、空のリストを定義しておき、そこにどんどん追加(append)していく処理をよく行います。

また、リストの豆知識として、リストの変数名には複数形で名前を付けることをおすすめします。
理由の1つとしては、変数名を見ただけでリストであることが把握できること、そして、もう一つはfor文と相性が良いためです。
※ 詳しくは for文 の節で説明します。

タプル

リストとは異なり、定義した後には変更ができない配列のことをタプルと呼びます。
複数の要素を一つにまとめたものであり、宣言は( )を使用する。
要素にアクセスする際には [ ] を使用する。

もちろん、タプルは書き換えるとエラーが起きます。

タプルは定数など、書き換えられたくない値に使用するようにしてください。
要素の抽出方法は基本的にリストと同じになっています。

辞書

キー(key)値(value)のペアを保持するリストのことです。
APIで使用されるJSONもこの形式で変数を保存することで、値に対する説明を行うことができます。

制御構文

for文:繰り返し

for文は繰り返しに使い、よく使う構文ですので、しっかりと使い方を覚えておきましょう。

まずは一番簡単な数値での繰り返しです。

for文含め、Pythonの構文では、:の後からは処理ブロックが始まり、スペース4つがそのブロック内であることを表します。
今回は、print(i)という処理がfor文の中に入っており、これを繰り返すことがわかります。

rangeを使用することで、特定回数の繰り返しが行われます。
ここで、注意として、range(5)と指定すると、「0,1,2,3,4」と0から始まることに注意しましょう。
0から始まることで、リストの要素番号へうまくアクセスすることができます。

そして、このrange(5)で作成されたリストの要素一つ一つを取り出して、一時的な変数であるiに格納して、処理を実行するといった流れです。
もちろん、一時的な変数名はiでなくても大丈夫ですが、要素番号を指定するときには、よくiを使用したりします。

リストの要素番号として、各要素を取り出す時は以下のように記述できます。

ただし、range(3)と今回はリストの要素数を数値で指定しましたが、これは汎用性の低いプログラムであるため、もう少し汎用性を高めるため、自動的に要素数を取得する方法を考えましょう。

こちらのlenを使用することでリストの要素数を取得できます(lengthのlen)。

こちらを使用した汎用性を高めたfor文は以下のとおりです。

ただし、こちらの書き方はPython流ではありません。
Python流の書き方では、要素番号を指定するのではなく、以下のように記述します。

いかがでしょうか。
非常にスッキリとかけており、こういったプログラムを**可読性が高い**といいます。
可読性が高いと他の人に伝わりやすいだけでなく、バグを生み出す可能性も下げることが出来るため、可読性の高いプログラムを目指しましょう。

また、for文でよく使うのが、要素番号も取得しながら繰り返すenumerateと、2つのリトを同時に繰り返すzipです。

まず、enumerateから使い方を見てみましょう。

(要素番号, 要素)と入ってくるので、そちらを使うことができます。

つぎに、zipの使い方を見てみましょう。

Python流でない従来の書き方も参考のために示しておきました。
こちらは(リスト1の要素, リスト2の要素)という順番で入ってくるため、こちらを利用します。
3つ以上も記述することは可能ですが、その場合は従来の書き方のほうが簡単に記述できるため、2つまでであればzipがおすすめです。

if文:条件分岐

こちらもfor文と同じくよく使う構文です。

  • ==  等しい
  • !=  等しくない
  • <, >  大きい、小さい

例えば、valという変数が0より大きい(正の値)かそうでないかを判定するときは以下のように記述します。

こちらの実行結果は正の値ですと表示されるはずです。
if文もfor文と同様、:(コロン)でブロックを区切ります。

elseはそれ以外という意味であり、valが0よりも大きくなければ、すべてこちらの処理が実行されます。

また、条件が一つだけでなく、条件が当てはまらない場合に、更に追加の条件を付ける場合は、elifを使います。

関数

一番簡単な関数

関数は複数の処理をまとめて使いたい時に、再利用性を高めるために使用するものです。

まずは一番簡単な関数を作ってみましょう。

こちらを実行してみましょう。

このように、関数は定義した後に実行することで、いつでも再利用することができます。

入力(引数)のある関数

先ほどの関数では、常に同じ処理しかできません。
これでは、汎用性が高いとはいえません。

そこで、「キカガク」や「吉崎」といった名前を自由に変えられるように入力(引数)の値を変えられる関数を作りましょう。

こちらのように、「こんにちは、○○さん」といったように入力の値によって、出力結果が変わるようになっています。
この「○○」に対応する部分を一時的にnameという変数が入力されると仮定して、この処理を書いていくわけです。
ここで、文字列の中に{ }が入っており、その後に、.format(name)と見覚えのない文法が来ています。
こちらはPythonでよく使うのですが、他の言語の%sのような機能であり、{ }に対応した場所に、.format()で指定した変数を格納するといった意味です。

こちらの関数を実行してみましょう。
実行時には、もちろんnameに対応する入力の値を与えて上げる必要があります。

出力のある関数

入力に引き続き、出力のある関数です。
先ほどまでの実行結果は、printで表示されることにとどまっており、計算した結果等を後で使いまわすことができない状況となっています。

試しに、先ほどの入力しか指定しないsay_hello2から出力された値を確認してみましょう。

こちらのように、messageという変数には何も格納されておらず、結果をあとで使うことができないわけです。

そこで、出力を設定してみましょう。
出力を設定することは簡単で、returnの後に出力したい変数を指定するだけです。

それでは、こちらを実行してみましょう。

こちらのように、出力の値が渡せていることがわかると思います。

また、入力、出力ともに、,(カンマ)を使うことで複数を指定できます。

実践課題

絶対値を返す abs という関数を作ってください。
※ 入力と出力をもたせること。

出力のイメージ
– abs(-1) -> 1
– abs(-5.2) -> 5.2
– abs(3) -> 3

解答

実行結果

発展課題

数値を格納したリストに対しても、リストで絶対値を返す関数を作ってください。

出力のイメージ
– numbers = [-1, 3, -5.2] – abs2(numbers) -> [1, 3, 5.2]

解答

実行結果

補足:リストの閉包表記

単純なfor文と単純な関数等を組み合わせる時に、空のリストを定義して、そこにfor文でappendして、と書くことができますが、もっとスッキリとした表現にできます。
それが、リストの閉包表記と呼ばれる書き方です。

さきほどのabs2のソースコードをリストの閉包表記を使って、さらにスッキリとした記述にしてみましょう。

いかがでしょうか。
慣れるとこちらの記述のほうが、 可読性が高いため、ぜひこちらを使うようにしてください。

クラスとは

変数や関数をひとまとまりで扱うことの出来る概念のことです。
関数を作ることはありますが、なかなかクラスを作るといった経験はないかもしれません。
基本的には、それほど大きなプロジェクトを作らない場合にはクラスとは遭遇しないケースが多いのですが、Chainerなどのプログラムを読む際にわかっておいた方が良い事項がありますので、必要最小限にてクラスを理解できるようにご説明していきます。

クラスとして定義を行い、それを実態化させることをインスタンス化と呼びます。

関数を持ったクラス

Pythonでのクラスは以下のように定義します。

クラスは定義するだけでは実態を持たず、概念のような存在です。

MyClassクラスをインスタンス化

そのため、実際を持たせるには インスタンス化 を行います。

クラスを定義して、そのクラスをインスタンス化(aという変数にインスタンスを代入)し、その関数の中のsay_helloを実行しています。

練習問題

a.say_hello2("キカガク")と実行すると、こんにちは、キカガクさんと表示するような say_hello2 を作ってください。

解答:クラスの定義

解答:インスタンス化

クラス変数もったクラス(クラス変数編)

クラスには関数意外にも変数をもたせることができます。
変数の値は基本的にはインスタンス内で保持されます。

インスタンス化

このクラス変数は簡単に代入もできます。

クラス変数へ代入

また、クラス変数の性質として、単純に書き換えることができません。

クラス変数に代入できるか確認

クラス変数をクラス内の関数によって書き換えたい場合は、以下のようにMyClass.nameのように変数名を指定する必要があります。

クラス変数の書き換え

ただし、クラス変数には思わぬ落とし穴があります。
それは、クラス内で変数の値を保持するため、別のインスタンスを作成した際にも、そのクラス変数の値が他のインスタンスへ共有されてしまいます。

他のインスタンスを作るが、最初からnameが”キカガク”となっている

他のインスタンスを作る場合は基本的に独立して変数を保持したいケースが多いため、クラス変数とは異なるインスタンス変数という別構造の変数を使用します。

インスタンス変数を持ったクラス

インスタンス変数はクラス変数とは異なり、インスタンスごとに独立に保持される変数です。
そのため、クラス内の変数の状況を毎回気にする必要はなく、独自のインスタンスの状況のみ把握しておけば良いため、考え方はシンプルです。
クラス内で変数を使用したい場合は、基本的にはインスタンス変数を使うようにしてください。

インスタンス変数を保持するクラス

インスタンス化

インスタンス変数の確認

練習問題

name1name2 の2つのインスタンス変数を保持するクラスを作成してください。

インスタンス変数を保持するクラス

インスタンス化

call関数を持ったクラス

__call__ という事前に準備されている関数を使用することで、クラスを関数風に実行することができます。
これは実際にChainerでも使用するので、覚えておきましょう。

__call__を使ったクラス

インスタンス化して、関数風に__call__の中身を呼び出して見ましょう。

call関数を実行