【技術記事】kerasのエラー解消方法、ValueError: Data cardinality is ambiguous: とはなんぞや?

みなさん、こんにちは、
みむすたーです。

本日は、

ValueError: Data cardinality is ambiguous: と言うエラーが出て解消できない!

と言うお悩みにお答えします。

私自身、このエラーに1時間ほど悩まされ、ようやく解消できました。
みなさんには、すぐに解決していただけるよう、説明していきたいと思います。

それでは、いきましょう。

もくじ

エラーの意味

ValueError: Data cardinality is ambiguous:

データの集合に含まれる要素の数が曖昧だと言われています。

ソースコード

私の場合、以下のコードでこのエラーが発生しました。
理由は、もちろんmodel.fit()関数に指定するlearn_datasに問題がありました。
では、どのように問題があったか次の項目でご説明します。

%tensorflow_version 2.x
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf
from tensorflow.keras import layers, models
from sklearn import datasets

# 順伝播
model = models.Sequential()
# 入力層 - 隠れ層 のモデル追加
model.add(layers.Dense(32,activation='relu',input_shape=(64,),name="relu_layer"))
# 隠れ層 - 出力層 のモデル追加
model.add(layers.Dense(10,activation='softmax',input_shape=(32,),name="softmax_layer"))

# 最適化関数=adam、誤差関数=クロスエントロピー、評価関数=多項分類器、で設定
model.compile(optimizer="adam",
              loss="binary_crossentropy",
              metrics=["categorical_accuracy"])

# 手書きの10進数データを取り出す
datas = datasets.load_digits().data
target_index_list = datasets.load_digits().target

# one-hot表現への変換
target = np.zeros((len(target_index_list),10))
for i, target_index in enumerate(target_index_list):
  target[i][target_index] = 1

# 学習用データとテストデータを分ける
learn_datas = []
learn_datas.extend(datas[0::3])
learn_datas.extend(datas[1::3])

learn_target = []
learn_target.extend(target[0::3])
learn_target.extend(target[1::3])
test_datas = datas[2::3]
test_target = target[2::3]

# 学習開始
history = model.fit(learn_datas,learn_target,batch_size=len(learn_datas),epochs=2000,verbose=0)

# 学習後データ取得
middle_weight, middle_bias, last_weight, last_bias = model.get_weights()

# テストデータで出力を試みる
middle_u = np.dot(test_datas, middle_weight) + middle_bias
middle_out = np.maximum(0, middle_u)
last_u = np.dot(middle_out, last_weight) + last_bias
last_out = np.exp(last_u) / np.sum(np.exp(last_u))

上のpythonのコードを実行した結果は以下の通りです。

sr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/data_adapter.py in __init__(self, x, y, sample_weights, sample_weight_modes, batch_size, epochs, steps, shuffle, **kwargs)
    280             label, ", ".join(str(i.shape[0]) for i in nest.flatten(data)))
    281       msg += "Please provide data which shares the same first dimension."
--> 282       raise ValueError(msg)
    283     num_samples = num_samples.pop()
    284 

ValueError: Data cardinality is ambiguous:

エラーの理由

model.fitで2次元配列を指定する場合は、本来以下のように指定する必要があります。

# OKなパターン
array(
[[1., 0., 0., 0., 0., 0., 0., 0., 0., 0.], 
[0., 0., 0., 1., 0., 0., 0., 0., 0., 0.], 
[0., 1., 0., 0., 0., 0., 0., 0., 0., 0.], 
[0., 0., 0., 0., 1., 0., 0., 0., 0., 0.]])

しかし、私の場合は、上のコードで以下のような形の配列を設定していました。

# NGなパターン
[array([1., 0., 0., 0., 0., 0., 0., 0., 0., 0.]), 
array([0., 0., 0., 1., 0., 0., 0., 0., 0., 0.]), 
array([0., 1., 0., 0., 0., 0., 0., 0., 0., 0.]), 
array([0., 0., 0., 0., 1., 0., 0., 0., 0., 0.])]

arrayはnumpyの配列 nparray のことです。
なぜ下側の配列指定だとダメだったかと言うと、
以下のリンクで記載されている通りなんですが、
https://keras.io/ja/models/model/

model.fitの引数 x で指定する配列は、nparrayでなければならなかったのです。
下側の配列指定を見ると、pythonのプリミティブな配列で囲っています。
そのため、kerasでエラーが出力されています。

内容は以上です。

コメント