AI 実装検定への道(6)
AI 実装検定 A級合格へ向けて学習を進めています。
前回投稿が5回目で、引き続きGoogle Colaboratoryを利用してプログラミングの章を進めて書いています。
第5回では、若干スローペース。行列(配列)を生成し、viewで取り出し、一部を修正したり、元データを変更したくない場合は、copyを使う方法。行列(配列)の形状(shape)を変更するのに、reshapeを使うこと。reshapeならびにnewaxisを利用して、1次元から2次元へ、行、列共に変更をして、concatenateを利用した連結をするところまで学びました。
公式テキストでは、207ページの下端から再開します。
多次元の配列(行列)の連結
まず、2×3の4〜9までの配列(行列)を準備します。
(コード記述)
import numpy as np
grid=np.array([[4,5,6],[7,8,9]])
これの形状を「shape」で確認してみます。
(コード記述)
grid.shape
(結果)
(2, 3)
この通り、2×3の配列(行列)であると示されました。
一次元配列と同様に2次元配列でも、concatenateを利用して連結できるとのこと。ただし、縦方向、横方向の連結する方向が2種あるわけなので、「axis」でそれを指定せねばなりません。
行方向(縦)に連結する場合は、「axis=0」。
縦方向(横)に連結するためには、「axis=1」とするとのこと。
grid2として、先ほどの配列(行列)を行方向(縦)に連結してみましょう。
(コード記述)
grid2=np.concatenate([grid,grid],axis=0)
grid2
(結果)
array([[4, 5, 6],
[7, 8, 9],
[4, 5, 6],
[7, 8, 9]])
この通り、4×3の配列(行列)が生成されました。
今一度、この形状を「shape」で確認してみます。
(コード記述)
grid2.shape
(結果)
(4, 3)
この通り、4×3の配列(行列)であると示されました。
次にgrid3として、先ほどの配列(行列)を列方向(横)に連結してみましょう。
(コード記述)
grid3=np.concatenate([grid,grid],axis=1)
grid3
(結果)
array([[4, 5, 6, 4, 5, 6],
[7, 8, 9, 7, 8, 9]])
この通り、2×6の配列(行列)が生成されました。
今一度、この形状を「shape」で確認してみます。
(コード記述)
grid3.shape
(結果)
(2, 6)
「axis=1」とすることで、2×3の配列を列方向(横)に連結し、その結果2×6の配列を生成し、「axis=0」では前述の通り、行方向(縦)に連結し4×3の配列を生成できました。
次に3次元の配列の連結を行います。
まず最初に、0〜15までの数字をランダムに2×3の3次元配列を設定します。
(コード記述)
A=np.random.randint(16,size=(3,2,3))
A
(結果)
array([[[12, 14, 5],
[ 2, 15, 12]],
[[ 9, 14, 4],
[11, 11, 9]],
[[ 1, 2, 0],
[12, 14, 15]]])
この通り、2×3の3次元配列を生成しました。
先ほどの2次元配列同様に「axis=0」を利用して行方向(縦)に連結します。
(コード記述)
grid4=np.concatenate([A,A],axis=0)
grid4
(結果)
array([[[12, 14, 5],
[ 2, 15, 12]],
[[ 9, 14, 4],
[11, 11, 9]],
[[ 1, 2, 0],
[12, 14, 15]],
[[12, 14, 5],
[ 2, 15, 12]],
[[ 9, 14, 4],
[11, 11, 9]],
[[ 1, 2, 0],
[12, 14, 15]]])
この通り、2×3の6次元配列を生成しました。
今一度、この形状を「shape」で確認してみます。
(コード記述)
grid4.shape
(結果)
(6, 2, 3)
続いて、「axis=1」を利用して、2×3の3次元配列を列方向(横)に連結し4×3の3次元配列を生成します。
(コード記述)
grid5=np.concatenate([A,A],axis=1)
grid5
(結果)
array([[[12, 14, 5],
[ 2, 15, 12],
[12, 14, 5],
[ 2, 15, 12]],
[[ 9, 14, 4],
[11, 11, 9],
[ 9, 14, 4],
[11, 11, 9]],
[[ 1, 2, 0],
[12, 14, 15],
[ 1, 2, 0],
[12, 14, 15]]])
この通り、4×3の3次元配列を生成しました。
今一度、この形状を「shape」で確認してみます。
(コード記述)
grid5.shape
(結果)
(3, 4, 3)
この通り、4×3の3次元配列であることが示されました。
次に、「axis=2」というのが出てきました。
本来なら、公式テキストのように3次元ベクトルで、「axis=0」:奥、
「axis=1」:縦、「axis=2」:横、と理解すべきなんでしょうけれど・・・
2次元配列については、
行方向(縦)に連結する場合は、「axis=0」。
縦方向(横)に連結するためには、「axis=1」とする。
と理解したので、ここでは便宜上、配列(行列)内で『直接横に』連結すると私の理解では置き換えて書いておくことにします。
(コード記述)
grid6=np.concatenate([A,A],axis=2)
grid6
これで、最初の2×3の3次元配列(行列)を、2×6(配列(行列)内で『直接横に』連結)に拡張された3次元配列(行列)を生成することになります。
(結果)
array([[[12, 14, 5, 12, 14, 5],
[ 2, 15, 12, 2, 15, 12]],
[[ 9, 14, 4, 9, 14, 4],
[11, 11, 9, 11, 11, 9]],
[[ 1, 2, 0, 1, 2, 0],
[12, 14, 15, 12, 14, 15]]])
形的にはそのようになっているように見えますが、念の為この形状を「shape」で確認してみます。
(コード記述)
grid6.shape
(結果)
(3, 2, 6)
これをそのまま読もうとするなら(3次元配列、2、×6)の配列と読むといいですね。当初の意図の通り、2×6(配列(行列)内で『直接横に』連結)に拡張された3次元配列(行列)を生成出来たことが示されました。
実は、ここまではすでに学習を進めていたもので、noteに記述を残し自身の振り返りにも役立てようと最初からやり直した結果がここまでです。さてさて、次から始めてみるページに突入します。
落ち着いて引き続き進めていきますね。
NumPyで演算
ここからは、配列(行列)の計算(足し算、引き算、掛け算、割り算)を進めていくようです。これ、高校時代に知っていればノートの上で悩まずに済んだかもしれませんね。あの頃の女性の数学教員には申し訳ないですが、配列(行列)は苦手分野でした。それ故、AI 実装検定 A級合格もかなり勉強せねばと冷や汗もので取り組んでいます。
では、まず最初に1〜5までの数字で1次元配列を生成してみます。
(コード記述)
B=np.arange(1,6)
B
(結果)
array([1, 2, 3, 4, 5])
まずは、上のBに対し、足し算(+)、引き算(ー)、掛け算(*)を使って計算してみます。割り算はちょっとややこしいみたいです。
(コード記述)
B+5
(結果)
array([ 6, 7, 8, 9, 10])
(コード記述)
B-1
(結果)
array([0, 1, 2, 3, 4])
(コード記述)
B*3
(結果)
array([ 3, 6, 9, 12, 15])
ここまでは、普通にExcel他で利用するので簡単ですね。
(プログラムは凄い!当然答えは間違っていない・・・)
割り算の場合、「/」(スラッシュ)、「//」(ダブルスラッシュ)、そして「%」を使う方法があるそうです。まずは、やってみます。
(コード記述)
B/2
(結果)
array([0.5, 1. , 1.5, 2. , 2.5])
(コード記述)
B//2
(結果)
array([0, 1, 1, 2, 2])
(コード記述)
B%2
(結果)
array([1, 0, 1, 0, 1])
なんだか分かりにくいですね・・・「B/2」としたときは、その解を少数で表してくれました。「B//2」ならびに「B%2」で一つの解になるのかな・・・1÷2=0余り1、2÷2=1余り0、3÷2=1余り1、4÷2=2余り0、5÷2=2余り1という風に「B//2」では0、1、1、2、2と商の部分を、「B%2」では1、0、1、0、1と余りの部分を表してくれています。
「*」を2つ付けると累乗になるらしい・・・パッと計算しにくいので2乗でやってみます。
(コード記述)
B**2
(結果)
array([ 1, 4, 9, 16, 25])
1×1=1、2×2=4、3×3=9、4×4=16、5×5=25・・・正解です!。一応、4乗とかやっておきますか!
(コード記述)
B**4
(結果)
array([ 1, 16, 81, 256, 625])
多分合っていると思う・・・
次から数字がややこしいです。
公式テキスト216ページの例を通して理解を進めます。
まず、10個の配列を持つ1次元配列(行列)を用意します。
(コード記述)
C=np.random.random(10)
C
(結果)
array([0.32791813, 0.9130427 , 0.35925242, 0.43224237, 0.85440495,
0.75267053, 0.76891071, 0.62157851, 0.8610786 , 0.59636509])
これ、最初・・・C=np.random.randam(10)と入力したみたいで、エラーが出てしまいました。下記のように・・・よく見ると、最後の行に、「numpy.random」には『randam』は適合しませんで〜!みたいなことが書いてありました。スペルが違うことも、こんなエラーメッセージで示してくれるなんて、優しいですね!
(スペル違いじゃない?的なメッセージだともっと嬉しいけど)
(エラー画面)
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
AttributeError Traceback (most recent call last)
<ipython-input-38-0133832c4615> in <module>
----> 1 C=np.random.randam(10)
2 C
AttributeError: module 'numpy.random' has no attribute 'randam'
では、気を取り直して進めます。
前述の10個のランダムに示された配列の各数値を合計するのに「sum」を利用するとのこと。
(コード記述)
np.sum(C)
(結果)
6.487464015530582
もはや、答えが正しいかはパッとは分かりませんが、Excelのsum式と同じように合計してくれるみたいです。この配列(行列)を示して合計や最大値、最小値を導くことも出来るそうです。
(コード記述)
C.sum()
(結果)
6.487464015530582
もちろん、前述と同じ数値です。
(コード記述)
np.max(C)
(結果)
0.9130427047971946
(コード記述)
C.max()
(結果)
0.9130427047971946
最初の配列(行列)の中では、0.9130427までしか表されていませんでしたが、まだ先があったのかな??
(コード記述)
np.min(C)
(結果)
0.3279181342005767
(コード記述)
C.min()
(結果)
0.3279181342005767
今日はここまでにしておきます。
公式テキストでは、217ページの中ほどまできました。
1次配列(行列)を準備して、合計、最大値(Max)、最小値(Min)を求めましたが、次は多次元の配列になるようなので、一旦小休止です。
今回は、前回同様にconcatenateを利用して多次元の配列(行列)を連結しました。この際、連結の方向を「axis」を利用して、行方向(縦)に連結する場合は「axis=0」、縦方向(横)に連結するためには「axis=1」、そして公式テキストの解説とは異なりますが配列(行列)内で『直接横に』連結させる場合には「axis=2」を利用すること。その度に、「shape」を利用して繰り返し配列(行列)の形状を確かめました。その後、NumPyでの計算として、パソコンでExcelを利用するのと同様に「+」「ー」「*」、ただし割り算をする場合は少数で商を求める「/」、商と余りをそれぞれ導く「//」と「%」を理解して、最後は配列(行列)の中から合計、最大値(Max)、最小値(Min)を求めました。
以上です。