このページで示している「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 ]