練習用のPythonコードサンプルその2
#プログラミング
このページについて
練習用のPythonコードサンプルその1の続きです
このページのコードは『Pythonで動かして学ぶ!あたらしい機械学習の教科書 第3版』を参考にしています
Pythonでの機械学習のプログラミングをする際に知っておくとよい内容です
Google Colabのセルに、同じように入力して、Shift + EnterまたはCtrl + Enter(Macの場合はCommand + Enter)を押すと、コードが実行され、結果が表示されます
自分の現在のスキルにあわせて、必要な部分を学習しましょう
学び方のコツ
コードはコピペしても構いませんが、できれば最初は自分で文字を打ち込んでみましょう
コードを実行したら、「少し数値を変えてみる」のように、アレンジして結果がどう変わるかを確認すると理解が深まります
このページの内容
このページは以下の内容についてのごく基本的な説明をしています。
(8) ベクトル
(9) 行列
(10) 行列(ndarray)の四則演算
(11) スライシング
(12) 関数
本ページで扱うのはかなり基本的なことのみです。もう少し詳しく学びたい場合は、たとえば別サイトの以下のページなど、いろいろなPython学習のサイトを見るなどして自主的に学習してください。
(8)~(10)の内容
16. NumPy (1): ベクトル — Python早見帳
17. NumPy (2): 行列・テンソル — Python早見帳
5-3. NumPyライブラリ — Pythonプログラミング入門 documentation
(11)の内容
6. リスト — Python早見帳
(12)の内容
関数の定義: ゼロからのPython入門講座 - python.jp
4. 関数 — Python早見帳
3-3. 関数 — Pythonプログラミング入門 documentation
hr.icon
(8) ベクトル
Numpyの利用
ベクトルや行列を使用するときにはNumpyというライブラリを使う
ライブラリ(用途ごとにクラスや関数などの機能がまとめられたもの)はimportで読み込んで使う
下のように書く
import numpy as np
as npは、Numpyをnpと省略して使うという意味になる(npでなくてもよいが、通例としてnpとすることがほとんどなので、npとしておくのがよい)
こうしておくと、以降はnp.array([1, 2])のように、np.関数名という形で機能を呼び出せる
ベクトルの定義
ベクトル(1次元配列)はnp.array(list型)で定義する
code:ベクトルの定義
x = np.array(1, 2)
x
上のようにxを直接表示させるのではなく、print(x)で表示させると表示形式が異なる
print(x)
2つのベクトルxとyを定義して、これを足してみる
ちゃんと[4 6]と、要素同士の足し算ができていることを確認しよう
code:ベクトルの和
x = np.array(1, 2)
y = np.array(3, 4)
print(x + y)
xの型を確かめると、numpy.ndarray型となっている
ここからは簡単にndarray型とよぶ
type(x)
なお、以下のように、list型を+でつなげても、ベクトルの要素を足すような演算にはならない(listの「連結」になる)。ベクトルとして扱う場合にはlist型ではなくndarray型を用いること
[1, 2] + [3, 4]
要素の参照
要素を参照するには、list型と同様に[ ]を使う
code:要素の参照
x = np.array(1, 2)
print(x0)
要素の書き換え
要素を書き換えるには、x[書き換えたい要素番号] = 数値とする
code:要素の書き換え
x = np.array(1, 2)
x0 = 100
print(x)
連続した整数のベクトルの作成
要素の値が1ずつ増えていくベクトル配列はnp.arange(n)で作れる
np.arange(n)とすると0からn-1までの配列
np.arange(n1, n2)とするとn1からn2-1までの配列
print(np.arange(10))
print(np.arange(5, 10))
ndarray型の注意点
ndarray型のaの中身をbにコピーするとき、通常の変数のようにb = aとするのではなく、b = a.copy()としないといけない
b = aとすると、「参照」がコピーされ、b = aとしたあとにbの内容を変更するとその変更がaにも反映されてしまう
下の2つのコードを試してみよう。上はb = aとした場合、下は正しくb = a.copy()とした場合
code:ndarray型をコピーするときの注意(不適切な例)
a = np.array(1, 1)
b = a
print('a =' + str(a))
print('b =' + str(b))
b0 = 100
print('b =' + str(b))
print('a =' + str(a))
code:ndarray型をコピーするときの注意(正しい例)
a = np.array(1, 1)
b = a.copy()
print('a =' + str(a))
print('b =' + str(b))
b0 = 100
print('b =' + str(b))
print('a =' + str(a))
なお、ndarray型だけでなく、list型でも同様のことが起こる
list型の場合には、import copyとしてcopyライブラリを読み込んだうえで、b = copy.deepcopy(a)とする
hr.icon
(9) 行列
行列の定義
行列は、ndarrayの2次元配列として以下のように定義する
code:行列
x = np.array(1, 2, 3], [4, 5, 6)
print(x)
行列のサイズ
ndarray型の変数(ベクトルや行列)のサイズは、変数名.shapeで取得できる
行列(2次元)であれば、(2, 3)のように、(行数, 列数)が得られる
code:行列のサイズ
x = np.array(1, 2, 3], [4, 5, 6)
x.shape
下のようにすると、この(行数, 列数)をそのまま変数に格納できる
code:行列のサイズの格納
h, w = x.shape
print(h)
print(w)
要素の参照
要素の参照は、次元ごとに,で区切って表す
行も列も、インデックスは0から始まるので注意
以下の例だと、「1行目」と「2列目」の要素を指すことになるので、
code:要素の参照
x = np.array(1, 2, 3], [4, 5, 6)
x1, 2
要素の書き換え
要素の書き換えは、ベクトルのときと同様
code:要素の書き換え
x = np.array(1, 2, 3], [4, 5, 6)
x1, 2 = 100
print(x)
要素が0や1のndarrayの作成
すべての要素が0のndarrayはnp.zeros(size)で作ることができる
以下は長さ10の(すべての要素が0の)ベクトルが作られる
code:要素が0のベクトル
x = np.zeros(10)
print(x)
sizeを(2, 10)のように与えれば、2×2の行列(2次元配列)が生成される
code:要素が0の行列
x = np.zeros((2, 10))
print(x)
同様に、たとえばsizeを(2, 3, 4)とすれば、2×3×4の行列(3次元配列)を生成できる(何次元でも可能)
code:要素が0の行列
x = np.zeros((2, 3, 4))
print(x)
すべての要素を1にしたい場合はnp.ones(size)とする
code:要素が1の行列
x = np.ones((2, 10))
print(x)
要素がランダムな行列の生成
要素がランダムな行列を生成する場合は、np.random.rand(size)が使える
各要素を0~1の一様分布から生成
sizeの書き方がnp.zeros(size)等と異なるので注意
np.random.rand(2, 3)
なお、np.random.randn(size)を使うと、平均0、分散1の正規分布からの乱数が生成できる
np.random.randint(low, high, size)を使うと、lowからhigh - 1までのランダムな整数値からなる、sizeの大きさの行列を生成できる
行列のサイズの変更
行列のサイズを変更するには、変数名.reshape(n, m)を使う
code:ベクトルのサイズ変更(変更前)
a = np.arange(10)
print(a)
code:ベクトルのサイズ変更(変更する)
a = a.reshape(2, 5)
print(a)
hr.icon
(10) 行列(ndarray)の四則演算
行列における四則演算
行列では、四則演算(+, -, *, /)は対応する要素ごとに行われる
code:行列における四則演算
x = np.array(4, 4, 4], [8, 8, 8)
y = np.array(1, 1, 1], [2, 2, 2)
print(x + y)
スカラー×行列
スカラーを行列にかけると、すべての要素に作用する
code:スカラー×行列
x = np.array(4, 4, 4], [8, 8, 8)
print(10 * x)
算術関数
Numpyにはさまざまな算術関数がある
たとえば平方根はnp.sqrt(x)、指数関数はnp.exp(x)
code:算術関数(平方根)
x = np.array(4, 4, 4], [9, 9, 9)
print(np.sqrt(x))
code:算術関数(指数関数)
x = np.array(4, 4, 4], [8, 8, 8)
print(np.exp(x))
その他の算術関数
対数関数np.log(x)、四捨五入np.round(x, 小数点以下の桁数)など
xのすべての要素に関する記述統計の計算を行う関数
平均値np.mean(x)、標準偏差np.std(x)、最大値np.max(x)、最小値np.min(x)など
行列の積の計算
行列の積はdot()を用いる。行列vと行列wの積はv.dot(w)で計算できる
code:行列の積の計算
v = np.array(1, 2, 3], [4, 5, 6)
w = np.array(1, 1], 2, 2, [3, 3)
print(v.dot(w))
hr.icon
(11) スライシング
スライシングの利用
listやndarrayで、要素の一部をまとめて表すスライシングという機能がある
変数名[:n]で、0からn-1までの要素を一度に参照する
code:スライシング
x = np.arange(10)
print(x)
print(x:5)
変数名[n:]とすると、nから最後の要素までが参照される
print(x[5:])
変数名[n1:n2]とすると、n1からn2-1の要素までが参照される
print(x[3:8])
変数名[n1:n2:dn]とすると、n1からn2-1の要素まで、dnおきで参照される
print(x[3:8:2])
以下のようにすると、配列の順番が逆向きになる
print(x[::-1])
スライシングは1次元以上のndarrayでも使える
code:ndarrayでのスライシング
y = np.array(1, 2, 3], 4, 5, 6, [7, 8, 9)
print(y)
print(y:2, 1:2)
hr.icon
(12) 関数
関数の利用
プログラムの一部は関数としてまとめることができる,
何度も繰り返し使うコードは関数にしてしまうと便利
関数を定義するには、def 関数名():からはじめ、関数の内容をインデントして記述する
実行は関数名()とする
たとえば、以下のように書くとmy_func1という関数ができる
code:関数
def my_func1():
print('Hi!')
この関数は、以下で実行できる
my_func1()
関数に値を渡すときには、たとえば値aとbを渡したい場合は、def 関数名(a, b)とする
このaやbを引数(ひきすう)という
関数内での処置の結果として、変数の値を出力したいときは、return 変数名とする
これを戻り値という
たとえば、以下のように書くと、2つの変数aとbを受け取って足し合わせて出力する関数my_func2が定義できる
code:引数のある関数
def my_func2(a, b):
c = a + b
return c
この関数は、以下のように2つの引数を入れて実行する
この場合は、aに1が、bに2が渡されることになり、処理結果としてa + bの値が返ってくる
my_func2(1, 2)
引数や戻り値の型、複数の戻り値
どんな型でも引数や戻り値にできる
戻り値は複数定義できる
たとえば、なんらかのデータを1次元のndarray型で関数に渡して、その平均値と標準偏差を出力する関数は、以下のように書ける
code:複数の戻り値がある関数
def my_func3(D):
m = np.mean(D) # Dの平均値を求める
s = np.std(D) # Dの標準偏差を求める
return m, s
複数の戻り値は、受け取る変数を,で区切って書くことで受け取れる
code:複数の戻り値を受け取る
data = np.random.randn(100) # 平均0、標準偏差1の乱数を100個生成してdataに入れる
print(data) # dataの中身を表示する
data_mean, data_std = my_func3(data) # my_func3にdataを渡して実行し、戻り値m, sをそれぞれdata_mean, data_stdに入れる
print('mean:{0:.2f}, std:{1:.2f}'.format(data_mean, data_std))
(2024/6/19 修正と補足)近藤伸彦.icon
上のコードの最終行は、当初、
print('mean:{0:3.2f}, std:{1:3.2f}'.format(data_mean, data_std))
と書いてしまっていましたが、いま上にある通り、
print('mean:{0:.2f}, std:{1:.2f}'.format(data_mean, data_std))
が正しい形です。すみません。
{0:.2f}の0:や{1:.2f}の1:は、.format()内の引数の番号を示します。(この場合は0がdata_mean、1がdata_std)
.2fの部分は、表示する小数点以下の桁数を示しています。