このページで示している「Unityで行うシンプルなディープニューラルネットワーク」で行った学習済みデータを使って、
MicroPythonでAI判定などの実現に当たり、それに必要なNumpyの機能などを絞った自作のNumArrayクラスを紹介しているページです。
また、このNumArrayクラスを検証したコードを紹介します。
なお、以下で紹介したNumArrayクラスを利用し、学習データで初期化して判定するクラスをこのリンク先で紹介します。
# import server # 「https://manabu.quu.cc/up/ume/ume_esp32_python.html」のサーバーで動作させる場合、この2行を使う
# print=server.send # サーバーで動作させる場合で、printの出力をTCPクライアントに送信する
# (numarray.pyの名前で作成)
import math
import struct
import io
import random
random.seed(123) # 乱数シードを123に設定 モジュールインポートで初期化
class NumArray:
def __init__(self, dim1:int=1, dim2:int = -1, dim3:int = -1): # create 相当
# 1次元、2次元、3次元のサイズだけを指定した初期化生成
dim2 = 0 if dim2 < 0 else dim2
dim3 = 0 if dim3 < 0 else dim3
self.shapeR = [dim1, dim2, dim3]
dim2 = 1 if dim2 == 0 else dim2
dim3 = 1 if dim3 == 0 else dim3
self.array = [0.0] * (dim1 * dim2 * dim3)
#
def __getitem__(self, index):
if not isinstance(index, tuple) or len(index) != 3:
raise TypeError("インデックスは (dim1, dim2, dim3) のタプルである必要があります")
i1, i2, i3 = index
dim1 = self.shapeR[0] # 1次元サイズ
idx = i3 * (dim1 * self.shapeR[1]) + i2 * dim1 + i1 # 1次元の配列に相当する添え字を求める
#print(f"array[{idx}]");
return self.array[idx]
#
def __setitem__(self, index, value):
i1, i2, i3 = index
dim1 = self.shapeR[0] # 1次元サイズ
idx = i3 * (dim1 * self.shapeR[1]) + i2 * dim1 + i1 # 1次元の配列に相当する添え字を求める
self.array[idx] = value
@classmethod
def createByArray(cls, buf,dim1:int=0, dim2:int = 0):
# buf のリストで初期化したNumArrayを、次元指定で生成する
dim2 = 0 if dim2 < 0 else dim2
n = len(buf)
na = NumArray(n)
na.array = [0.0] * n
for i in range(len(buf)): na.array[i] = buf[i] # コピー
if dim1 == 0: # 第1引数省略時
na.shapeR[0] = n; # 1次元
na.shapeR[1] = na.shapeR[2] = 0
else: # 2次元または3次元
na.shapeR[0] = dim1
if dim2 == 0: # 第2引数省略時
na.shapeR[1] = int(n / (dim1) + 0.5)
na.shapeR[2] = 0; # 次元の個数が2
else:
na.shapeR[1] = dim2
na.shapeR[2] = int(n / (dim1 * dim2) + 0.5) # 次元の個数が3
#
#
return na
#
def __str__(self):
if self.shapeR[0] == 0:
return f" {self.array[0],8:F4}"
_MAX_LINE=5 # (この数×2)行より大きい場合、内部を表略表示
brackets0 = False # 始まりのカッコ出力済みでTrue
brackets1 = False
brackets2 = False
flagLF = False # ]の出力で直後に改行が必要な時にTrue
dim1 = 1 if self.shapeR[1] == 0 else self.shapeR[1]
dim2 = 1 if self.shapeR[2] == 0 else self.shapeR[2]
bS1 = "" if self.shapeR[1] == 0 else "["
bS2 = "" if self.shapeR[2] == 0 else "["
bE1 = "" if self.shapeR[1] == 0 else "]"
bE2 = "" if self.shapeR[2] == 0 else "]"
start5line = ""
s = ""
countLF = 0
s += f"{self.shapeR[0]}, {self.shapeR[1]}, {self.shapeR[2]}\n"
for i in range(len(self.array)+1):
s0 = i % self.shapeR[0] == 0
s1 = i % (self.shapeR[0] * dim1) == 0
s2 = i % (self.shapeR[0] * dim1 * dim2) == 0
if s0 and brackets0:
s += "]"
brackets0 = False
flagLF = True
if s1 and brackets1:
s += bE1
brackets1 = False
if s2 and brackets2:
s += bE2
brackets2 = False
if i == len(self.array): break
if flagLF:
s += "\n"
countLF += 1
if countLF == _MAX_LINE:
start5line = s # 先頭の5行まで記憶
s = ""
elif countLF >= _MAX_LINE and s.count('\n') >= _MAX_LINE:
i_LF = s.find('\n')
s = s[i_LF+1:] # _MAX_LINE行を超えないようにsの内容制御
flagLF = False
if s2 and not brackets2:
s += bS2
brackets2 = True
if s1 and not brackets1:
s += bS1
brackets1 = True
if s0 and not brackets0:
s += "["
brackets0 = True
s += f" {self.array[i]:8.4f} " # 要素の表示
#
if countLF >= _MAX_LINE * 2: s = start5line + " . . . . . .\n" + s
else: s = start5line + s
return s
#
#
def deepcopy(self) -> 'NumArray':
# 自身のNumArrayを複製
naC = NumArray(self.shapeR[0], self.shapeR[1], self.shapeR[2])
for i in range(len(self.array)):
naC.array[i] = self.array[i]
return naC
#
#
def add_scalar(self, v: float) -> 'NumArray':
#行列に対するスカラー加算した行列に変更
for i in range(len(self.array)): self.array[i] += v
return self
#
#
def mul_scalar(self, v:float) -> 'NumArray':
#行列に対するスカラー乗算した行列に変更
for i in range(len(self.array)): self.array[i] *= v
return self
#
#
def add_matrix(self, na:'NumArray') -> 'NumArray':
#行列の各要素を加算した要素に変更
if self.shapeR[0] != na.shapeR[0] or self.shapeR[0] != na.shapeR[0]:
s = f"add_matrix:{self.shapeR[0]}!={na.shapeR[0]} or {self.shapeR[0]}!={na.shapeR[0]}"
raise Exception(s)
for i in range(len(self.array)): self.array[i] += na.array[i]
return self
#
#
def mul_matrix(self, na:'NumArray') -> 'NumArray':
#行列の各要素を乗算した要素に変更
if self.shapeR[0] != na.shapeR[0] or self.shapeR[0] != na.shapeR[0]:
s = f"mul_matrix:{self.shapeR[0]}!={na.shapeR[0]} or {self.shapeR[0]}!={na.shapeR[0]}"
raise Exception(s)
for i in range(len(self.array)): self.array[i] *= na.array[i]
return self
#
#
def exp(self)->'NumArray':
# 要素全てで、ネイピア数eの累乗を求め、xの要素に設定
for i in range(len(self.array)): self.array[i] = math.exp(self.array[i])
return self
#
#
def sigmoid(self)->'NumArray':
# シグモイド関数 (arrayの全要素を0〜1.0に変換したNumArrayの生成)
na = NumArray(self.shapeR[0], self.shapeR[1], self.shapeR[2])
for i in range(len(self.array)):
na.array[i] = 1/(1+math.exp(-self.array[i]))
return na
#
#
@classmethod
def sum_of_products(cls,a:'NumArray', k:int , b:'NumArray', n:int) -> float:
# a行列のk行とb行列のn列において、各要素を積の総和を求める
rtnv = 0
for i in range(a.shapeR[0]):
# print(f"a[{i}, {k}, 0] * b[{n}, {i}, 0]"); #Debug
rtnv += a[i, k, 0] * b[n, i, 0]
#
return rtnv
#
#
@classmethod
def createParam(cls, param:float, dim1:int , dim2:int=1, dim3:int=0) -> 'NumArray':
# paramの値の要素で、1次元をdim1、2次元をdim2、3次元をdim3にして、NumArrayを生成
dim2 = 0 if dim2 < 0 else dim2
dim3 = 0 if dim3 < 0 else dim3
na = NumArray(dim1, dim2, dim3)
for i in range(len(na.array)): na.array[i] = param
na.shapeR[0] = dim1
na.shapeR[1] = dim2
na.shapeR[2] = dim3
return na
#
#
@classmethod
def dot(cls , a:'NumArray', b:'NumArray')-> 'NumArray':
# 行列の積 戻り値: a × b
if a.shapeR[0] != b.shapeR[1]:
msg = f"a dim1 size:{a.shapeR[0]} != b dim2 size:{b.shapeR[1]}"
raise Exception(msg)
#
c = NumArray.createParam(0, b.shapeR[0], a.shapeR[1])
row_size = 1 if c.shapeR[1] == 0 else c.shapeR[1]
for row in range(row_size): # 行の繰り返し
for column in range(c.shapeR[0]): # 列の繰り返し
c[column, row, 0] = NumArray.sum_of_products(a, row, b, column)
#
#
return c
#
#
def read(self, f:io.BufferedReader) -> 'NumArray':
# fのファイルリーダーからNumArrayのバイナリーを読み取って、デシリアライズする
self.shapeR=[1,1,1]
self.shapeR[0]=struct.unpack("<i", f.read(4))[0] # リトルエンディアンの32bit整数を読み込む
self.shapeR[1]=struct.unpack("<i", f.read(4))[0] # リトルエンディアンの32bit整数を読み込む
self.shapeR[2]=struct.unpack("<i", f.read(4))[0] # リトルエンディアンの32bit整数を読み込む
self.array=[0.0]*self.shapeR[0]*(1 if self.shapeR[1]==0 else self.shapeR[1])*(1 if self.shapeR[2]==0 else self.shapeR[2])
#print(f"self.shapeR:{self.shapeR}, len(self.array): {len(self.array)}")
#
# i=0
# while(i<len(self.array)):
# bin=f.read(4)
# if(not bin): break
# self.array[i] = struct.unpack("<f", bin)[0]# リトルエンディアンの32bit浮動小数点数デコード
# #print(f"self.array[{i}]:{self.array[i]:10.5f}")
# i+=1
#
# ########上記の速度は遅かったの一括読み取りの次へ変更 20250731
# bin = f.read(len(self.array) * 4)
# self.array[:] = struct.unpack("<" + "f" * len(self.array), bin)
#
# ########上記は余計な記憶域binのサイズが大きいので次に変更 0801、(速度は前述とあまり変わらない)
buf = bytearray(4) # 再利用可能なバッファ
i = 0
while i < len(self.array):
n = f.readinto(buf)
if n < 4: break
self.array[i] = struct.unpack("<f", buf)[0]
i += 1
#
#
def write(self, f:io.BufferedWriter):
# NumArrayをシリアライズして、fのファイルライターが書き出す
f.write(struct.pack("<i", self.shapeR[0]))# リトルエンディアンの32bit整数を書き込む
f.write(struct.pack("<i", self.shapeR[1]))# リトルエンディアンの32bit整数を書き込む
f.write(struct.pack("<i", self.shapeR[2]))# リトルエンディアンの32bit整数を書き込む
size=self.shapeR[0]*(1 if self.shapeR[1]==0 else self.shapeR[1])*(1 if self.shapeR[2]==0 else self.shapeR[2])
# i=0
# while(i<len(self.array[:size])):
# f.write(struct.pack("<f", self.array[i] ))# リトルエンディアンの32bit浮動小数点数を書き込む
# #print(f"{self.array[i]:10.5f}")
# i+=1
#
# (20250730) 上記のファイル書き込み繰り返しでは遅過ぎるので、次のように、
# bufのバイト配列に、浮動小数点数を4バイトずつ格納する繰り返し後、一括で書き込みするように変更
i=0
buf = bytearray(size*4)
while(i<size):
struct.pack_into('<f', buf, i * 4, self.array[i] ) # リトルエンディアンの32bit浮動小数点数を格納
# if(i % 1000 == 0): print(f"[{i}]{self.array[i]:10.5f}")
i+=1
#
f.write(buf)
#
#
@classmethod
def T(cls, na: 'NumArray' )->'NumArray':
# 転置行列 行列の行と列を入れ替えた行列としてNumArrayの生成して返す。
y = na.deepcopy()
y.shapeR[0] = na.shapeR[1]
y.shapeR[1] = na.shapeR[0]
y.shapeR[2] = 0
nRow = 1 if na.shapeR[1] == 0 else na.shapeR[1]
nColumn = 1 if na.shapeR[0] == 0 else na.shapeR[0]
idx = 0
for col in range(nColumn):
for row in range(nRow):
y.array[idx] = na[col, row, 0]
idx+=1
#
#
return y
#
#
@classmethod
def sum(cls, x:'NumArray', axis:int = -1)-> 'NumArray':
# 集計する。axis=-1の場合、y.array[0] に合計が設定される。
nRow = 1 if x.shapeR[1] == 0 else x.shapeR[1]
nColumn = 1 if x.shapeR[0] == 0 else x.shapeR[0]
sumV = 0
if axis == -1: # 全合計
for i in range(len(x.array)): sumV += x.array[i]
y = NumArray(1)
y.array[0] = sumV
elif axis == 0: # 同列の各要素を集計
y = NumArray(nColumn)
for column in range(nColumn):
for row in range(nRow):
y.array[column] += x[column, row, 0]
#
#
elif axis == 1: # 同行の各要素の集計
y = NumArray(nRow)
for row in range(nRow):
for column in range(nColumn):
y.array[row] += x[column, row, 0]
#
#
return y
#
#
@classmethod
def max(cls, x:'NumArray', axis:int = -1)->'NumArray':
# 集計する。axis=-1の場合、y.array[0] に最大値が設定される。
nRow = 1 if x.shapeR[1] == 0 else x.shapeR[1]
nColumn = 1 if x.shapeR[0] == 0 else x.shapeR[0]
maxV = -3.402823e+38
if axis == -1:
for i in range(len(x.array)):
if x.array[i]> maxV: maxV= x.array[i]
y = NumArray(1)
y.array[0] = maxV
elif axis == 0: # 同列の各要素で求める
y = NumArray(nColumn)
for column in range(nColumn):
y.array[column] = -3.402823e+38
for row in range(nRow):
if x[column, row, 0] > y.array[column]:
y.array[column] = x[column, row, 0]
#
#
elif axis == 1: # 同行の各要素で求める
y = NumArray(nRow)
for row in range(nRow):
y.array[row] = -3.402823e+38
for column in range(nColumn):
if x[column, row, 0] > y.array[row]:
y.array[row] = x[column, row, 0]
#
#
return y
#
#
def createLineAt(self, idx: int)->'NumArray':
# 自身が2次配列、または3次配列の場合に、idx行を抽出した1次または2次配列を返す。
if self.shapeR[1] == 0:
raise Exception(f"This method is not available for this structure self.shapeR:{self.shapeR}")
if self.shapeR[1] <= idx:
raise Exception(f"not available createLineAt({idx}) because self.shapeR[0]:{self.shapeR[0]}")
if self.shapeR[2] == 0:
naA = NumArray(self.shapeR[0], 0, 0) # 1次元配列を抽出
for i in range(self.shapeR[0]): naA[i,0,0]=self[i, idx, 0]
else:
naA = NumArray(self.shapeR[0], self.shapeR[1], 0) # 2次元配列を抽出
for i2 in range(self.shapeR[1]):
for i in range(self.shapeR[0]):
naA[i,i2,0]=self[i, i2, idx]
#
return naA
#
@classmethod
def softmax(cls, x:'NumArray')->'NumArray':
# ソフトマックス関数:xを確率的な値に変換する。
# x要素群のごちゃごちゃした数字を、最終総和が100%(1.0)になる比率に変えてくれる関数
maxX = NumArray.max(x) # maxX.array[0] に最大値
x =x.deepcopy()
x.add_scalar(- maxX.array[0]) # オーバーフロー対策
# print(f"- maxX.array[0]:{-maxX.array[0]}, x:{x}")
naY = x.exp()
na_sum = NumArray.sum(naY).array[0]
naY.mul_scalar(1 / na_sum)
return naY
#
def setNumpy(self, npA):# これは、numpy とのコンバートメソッド-で、利用時は「import numpy」が必要
''' numpy のnpA で自身を初期化する '''
self.array=list(npA.flatten())
self.shapeR=[0,0,0]
if npA.ndim == 1 : self.shapeR[0]=npA.shape[0]
elif npA.ndim == 2 :
self.shapeR[0]=npA.shape[1]
self.shapeR[1]=npA.shape[0]
elif npA.ndim == 3 :
self.shapeR[0]=npA.shape[2]
self.shapeR[1]=npA.shape[1]
self.shapeR[2]=npA.shape[0]
#
#
def getNumpy(self):# これは、numpy とのコンバートメソッド-で、利用時は「import numpy」が必要
''' 自身のデータに対応するnumpy を生成して返す '''
npA=np.array(self.array)
if self.shapeR[1]!=0:
if self.shapeR[2]!=0: npA=npA.reshape(self.shapeR[2], self.shapeR[1], self.shapeR[0]) #3次元
else: npA=npA.reshape(self.shapeR[1], self.shapeR[0]) # 2次元
#
return npA
#
#
# 20250731 追加
@classmethod
def createGaussian(cls, dim1:int, dim2:int=1, dim3:int=1, mean:float=0, stdDev:float=1)->'NumArray':
# 正規分布乱数(ガウス分布乱数)で初期化したNumArrayの生成
dim2 = 0 if dim2 < 0 else dim2
dim3 = 0 if dim3 < 0 else dim3
na = NumArray(dim1, dim2, dim3)
na.shapeR[0] = dim1
na.shapeR[1] = dim2
na.shapeR[2] = dim3
for i in range(len(na.array)):
na.array[i] = normal_random(mean, stdDev)
#
return na;
# 20250801 追加
# 交差エントロピー誤差(Cross-Entropy Loss)を得る。正解ラベルと一致しているかを評価します。
@classmethod
def cross_entropy_error(cls, y:'NumArray', t:'NumArray')->float:
# tが正解ラベル(one-hot表現)で、yがモデルの予測確率 yがtに近ければこの絶対値が小さい値になる。(最小値はゼロ)
# print(f"y:{y}\nt:{t}");
rtnV = 0
for i in range( len(y.array) ):
rtnV += -math.log(y.array[i]) * t.array[i]
#
return rtnV
#
# 20250731 追加
# 正規分布乱数(ガウス分布乱数)
def normal_random(mu=0, sigma=1):
# [0,1) の一様乱数を2つ生成
u1 = random.random()
u2 = random.random()
# Box-Muller変換
z = math.sqrt(-2 * math.log(u1)) * math.cos(2 * math.pi * u2)
# 平均mu, 標準偏差sigmaにスケーリング
return mu + sigma * z
# xのNumArrayより、第1次の要素をidxFromの位置からnumb個をコピーして、それを返す
def copyNumArray(x:NumArray, numb:int, idxFrom:int)->NumArray:
x2=NumArray(x.shapeR[0], numb)
idx = x.shapeR[0] * idxFrom # ここからコピー
idxUntil = idx + x.shapeR[0] * numb # これ未満までコピー
i = 0
while(idx < idxUntil):
x2.array[i] = x.array[idx]
i+=1
idx+=1
return x2
na=NumArray(4,3,2) // float要素が4個、それが3個あり、それが2個並ぶ3次元配列
v=0
for i3 in range(2):
for i2 in range(3):
for i1 in range(4):
na[i1,i2,i3]=v // __setitem__が呼び出されている。
v+=1
for i3 in range(2):
for i2 in range(3):
for i1 in range(4):
print(f"{na[i1,i2,i3]}") # 0から23のデータが列挙できる。(__getitem__が呼び出されている)
なお、na[i1, i2, i3] の表現は、i1が1次元目の添え字、i2が2次元目、i3がの3次元目の添え字を意味します。
これは、一般の配列の順番の逆になっています。
buf = bytes([b for b in range(3 * 2 * 6)]) # byte列の生成
na=NumArray.createByArray(buf, 6,2) # 1次元目サイスが6,2次元目が2の3次配列にしている。(3次元目は自動的に残りのサイズで、3が設定)
print(na) # __str__(self) の確認
for i3 in range(na.shapeR[2]):
for i2 in range(na.shapeR[1]):
for i1 in range(na.shapeR[0]):
na[i1, i2, i3] /= 10; #変更
print(f"na[{i3}][{i2}][{i1}]:{na[i1, i2, i3]}") # 要素の表示
実行結果
6, 2, 3 [[[ 0.0000 1.0000 2.0000 3.0000 4.0000 5.0000] [ 6.0000 7.0000 8.0000 9.0000 10.0000 11.0000]] [[ 12.0000 13.0000 14.0000 15.0000 16.0000 17.0000] [ 18.0000 19.0000 20.0000 21.0000 22.0000 23.0000]] [[ 24.0000 25.0000 26.0000 27.0000 28.0000 29.0000] [ 30.0000 31.0000 32.0000 33.0000 34.0000 35.0000]]] na[0][0][0]:0.0 na[0][0][1]:0.1 na[0][0][2]:0.2 ・・・省略
na=NumArray.createByArray([1,2,3, 4,5,6], 3) # 1次元目が3,2次元目省略で、2次元配列となり、2次元のサイスは残り情報から自動的に2になっている)
na2=na.deepcopy() # ディープコピー
print(na2) # 表示
na2.add_scalar(-1) # 全要素に -1 を加算
print(na2) # 表示
na2.mul_scalar(10) # 全要素を 10 倍へ
print(na2) # 表示
na2.add_matrix(na) # na2 とnaで行列として加算(各要素で加算)
print(na2) # 表示
na2.mul_matrix(na) # na2 とnaで、各要素で積算
print(na2) # 表示
print(na) # 最初の変数に変化が無いことを確認
実行結果
3, 2, 0 ディープコピーしたオブジェクトの表示 [[ 1.0000 2.0000 3.0000] [ 4.0000 5.0000 6.0000]] 3, 2, 0 全要素に -1 を加算 [[ 0.0000 1.0000 2.0000] [ 3.0000 4.0000 5.0000]] 3, 2, 0 全要素を 10 倍 [[ 0.0000 10.0000 20.0000] [ 30.0000 40.0000 50.0000]] 3, 2, 0 na2 とnaで行列として加算 [[ 1.0000 12.0000 23.0000] [ 34.0000 45.0000 56.0000]] 3, 2, 0 na2 とnaで、各要素で積算 [[ 1.0000 24.0000 69.0000] [ 136.0000 225.0000 336.0000]] 3, 2, 0 [[ 1.0000 2.0000 3.0000] [ 4.0000 5.0000 6.0000]]
# dim1を指定しなければ1次元配列、dim1だけ指定すると2次元、dim1とdim2を0以外で指定すると3次元になる
na = NumArray.createByArray([ -2, -1, -0.5, 0, 3, 6 ],3) #/配列よりNumArrayを生成
# 上記で、配列のサイズから、1次元のサイズだけ指定すれば、2次元が自動的に分かり、3個が2列の2次元配列になる。
print(f"na = {na}") # 確認表示
with open("test.bin", mode='wb') as fr: na.write(fr) # シリアライズしてファイル化
naA=NumArray()
with open("test.bin", mode='rb') as fr: naA.read(fr) # デシリアライズ
print(f"naA = {naA}") # 復元でータが同じかの確認表示
naSigmoid = naA.sigmoid(); # データの範囲を0から1の値に変更するシグモイド
print(f"naSigmoid = {naSigmoid}") # シグモイドの確認表示
実行結果
na = 3, 2, 0 [[ -2.0000 -1.0000 -0.5000] [ 0.0000 3.0000 6.0000]] naA = 3, 2, 0 [[ -2.0000 -1.0000 -0.5000] [ 0.0000 3.0000 6.0000]] naSigmoid = 3, 2, 0 [[ 0.1192 0.2689 0.3775] [ 0.5000 0.9526 0.9975]]
naA = NumArray.createByArray([ 1,2,3,4,5,6,7,8,9,10,11,12 ], 3) # 4行3列
print(f"naA={naA}")
naB = NumArray.createByArray([ 1,2,3,4,5,6 ], 2) # 4行3列
print(f"naB={naB}")
naC = NumArray.dot(naA, naB) # 行列の積
print(f"\nnaA * naB = naC:{naC}")
naX = NumArray.createByArray([ 1, 2, 3, 4 ]) # 1行4列
print(f"naX:{naX}")
naY = NumArray.dot(naX, naC) # 行列の積
print(f"\nnaC * naX = naY:{naY}")
実行結果
naA=3, 4, 0 [[ 1.0000 2.0000 3.0000 ] [ 4.0000 5.0000 6.0000 ] [ 7.0000 8.0000 9.0000 ] [ 10.0000 11.0000 12.0000 ]] naB=2, 3, 0 [[ 1.0000 2.0000 ] [ 3.0000 4.0000 ] [ 5.0000 6.0000 ]] naA * naB = naC:2, 4, 0 [[ 22.0000 28.0000 ] 上記2つの積 [ 49.0000 64.0000 ] [ 76.0000 100.0000 ] [ 103.0000 136.0000 ]] naX:4, 0, 0 [ 1.0000 2.0000 3.0000 4.0000 ] naC * naX = naY:2, 0, 0 [ 760.0000 1000.0000 ] 上記2つの積
naX = NumArray.createByArray( [ 2.5, 4.0, 3.5 ] )
naY = naX.deepcopy()
print(f"NumArrayのnaX:{naX}\n NumArray.exp(naX):{naY.exp()}")
実行結果
NumArrayのnaX:3, 0, 0 [ 2.5000 4.0000 3.5000 ] NumArray.exp(naX):3, 0, 0 [ 12.1825 54.5982 33.1155 ]
# 転置行列検証
naA = NumArray.createByArray( [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ], 3)
print(f"NumArrayのnaX:{naA}\n")
t = NumArray.T(naA) # 転置行列を得る。
print(f"NumArrayのt:{t}\n")
実行結果
NumArrayのnaX:3, 4, 0 [[ 1.0000 2.0000 3.0000 ] [ 4.0000 5.0000 6.0000 ] [ 7.0000 8.0000 9.0000 ] [ 10.0000 11.0000 12.0000 ]] NumArrayのt:4, 3, 0 [[ 1.0000 4.0000 7.0000 10.0000 ] [ 2.0000 5.0000 8.0000 11.0000 ] [ 3.0000 6.0000 9.0000 12.0000 ]]
naX = NumArray.createByArray( [ 0,1,2,3,4,5,6,7,8,9,10,11 ], 3)
print(f"NumArrayのnaX:{naX}")
print(f"NumArray.sum(naX):{NumArray.sum(naX)}") # naX.array[0] が結果となります。
print(f"NumArray.sum(naX, 0):{NumArray.sum(naX, 0)}") # 同列の各要素を集計
print(f"NumArray.sum(naX, 1):{NumArray.sum(naX, 1)}") # 同行の各要素の集計
実行結果
NumArrayのnaX:3, 4, 0 [[ 0.0000 1.0000 2.0000 ] [ 3.0000 4.0000 5.0000 ] [ 6.0000 7.0000 8.0000 ] [ 9.0000 10.0000 11.0000 ]] NumArray.sum(naX):1, 0, 0 [ 66.0000 ] NumArray.sum(naX, 0):3, 0, 0 [ 18.0000 22.0000 26.0000 ] NumArray.sum(naX, 1):4, 0, 0 [ 3.0000 12.0000 21.0000 30.0000 ]
naX = NumArray.createByArray( [ 0,1,2,3,4,5,6,7,8,9,10,11 ], 3)
print(f"NumArrayのnaX:{naX}")
print(f"NumArray.max(naX):{NumArray.max(naX)}") # naX.array[0] が結果となります。
print(f"NumArray.max(naX, 0):{NumArray.max(naX, 0)}") # 同列の各要素の最大
print(f"NumArray.max(naX, 1):{NumArray.max(naX, 1)}") # 同行の各要素の最大
実行結果
NumArrayのnaX:3, 4, 0 [[ 0.0000 1.0000 2.0000 ] [ 3.0000 4.0000 5.0000 ] [ 6.0000 7.0000 8.0000 ] [ 9.0000 10.0000 11.0000 ]] NumArray.max(naX):1, 0, 0 [ 11.0000 ] NumArray.max(naX, 0):3, 0, 0 [ 9.0000 10.0000 11.0000 ] NumArray.max(naX, 1):4, 0, 0 [ 2.0000 5.0000 8.0000 11.0000 ]
idxTest = 2 # createLineAt(idxTest)によるidxTest行目抽出の実験
naA = NumArray.createByArray( [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ], 3)
print(f"NumArrayのnaA:{naA}")
naB = naA.createLineAt(idxTest)
print(f"NumArrayのnaB:{naB}")
naC = NumArray.createByArray( [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ], 2, 3)
print(f"\n{naC}\n[1]=createLineAt(1)={naC.createLineAt(1)}")
実行結果
NumArrayのnaA:3, 4, 0 [[ 1.0000 2.0000 3.0000 ] [ 4.0000 5.0000 6.0000 ] [ 7.0000 8.0000 9.0000 ] [ 10.0000 11.0000 12.0000 ]] NumArrayのnaB:3, 0, 0 [ 7.0000 8.0000 9.0000 ] 2, 3, 2 [[[ 1.0000 2.0000 ] [ 3.0000 4.0000 ] [ 5.0000 6.0000 ]] [[ 7.0000 8.0000 ] [ 9.0000 10.0000 ] [ 11.0000 12.0000 ]]] [1]=createLineAt(1)=2, 3, 0 [[ 7.0000 8.0000 ] [ 9.0000 10.0000 ] [ 11.0000 12.0000 ]]上記が目指したNumpyを利用するコードは次のようになります。
|
2次配列から添え字指定で1次配列を得る操作や、 3次配列から添え字指定で2次配列を得る操作の例。
import numpy as np
idxTest = 1
naA = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] ).reshape(4, 3)
print(f"NumpyのnaA:{naA}")
naB = naA[idxTest]
print(f"\n NumpyのnaB:{naB}") # 上記の2の要素の1次配列を得る
naC = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] ).reshape(2, 3, 2) # 上記の1の要素の2次配列を得る
print(f"\n{naC}\n\n [1]={naC[1]}")
|
この実行結果
NumpyのnaA:[[ 1 2 3] [ 4 5 6] [ 7 8 9] [10 11 12]] NumpyのnaB:[4 5 6] 得られた2の要素の1次配列 [[[ 1 2] [ 3 4] [ 5 6]] [[ 7 8] [ 9 10] [11 12]]] [1]=[[ 7 8] 得られた1の要素の2次配列 [ 9 10] [11 12]] |
naX = NumArray.createByArray( [ 2.5, 4.0, 3.5 ] ) #例えば、「人」、「ねこ」、「イヌ」の判定度合い
print(f"NumArrayのnaX:{naX}")
naY = NumArray.softmax(naX) # 確率情報に変換
print(f"naY=NumArray.softmax(naX):{naY}")
実行結果
NumArrayのnaX:3, 0, 0 [ 2.5000 4.0000 3.5000 ] naY=NumArray.softmax(naX):3, 0, 0 [ 0.1220 0.5465 0.3315 ]