質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.11%

tensorflow2.1を用いた深層学習でのエラー(NotImplementedError)

受付中

回答 0

投稿

  • 評価
  • クリップ 0
  • VIEW 87

aaa_ytooooo

score 4

前提・実現したいこと

tensorflow2.1を用いてNeural ODEモデルを構築し、入力が1次元、出力が1次元の回帰問題を解こうと思っております。

該当のソースコード

import tensorflow as tf
import numpy as np
from scipy.integrate import solve_ivp
from sklearn.utils import shuffle
from sklearn.model_selection import train_test_split

def get_dataset(N):
    x = np.linspace(0., 1., N).reshape(-1, 1)
    y = np.sin(np.pi * x)
    return (x, y)

def d_sigmoid(x):
    return tf.multiply(tf.nn.sigmoid(x), tf.subtract(1., tf.nn.sigmoid(x)))

class NeuralODEModel(tf.keras.Model):
    def __init__(self, dim_in, dim_out, max_time, division, function, d_function):
        super(NeuralODEModel, self).__init__(name='')
        self.dim_in = dim_in
        self.dim_out = dim_out
        self.max_time = max_time
        self.division = division
        alpha = tf.Variable(tf.multiply(eps, tf.ones(shape=(self.division, self.dim_out), dtype=tf.dtypes.float32)))
        beta = tf.Variable(tf.multiply(eps, tf.ones(shape=(self.division, self.dim_in, self.dim_in), dtype=tf.dtypes.float32)))
        gamma = tf.Variable(tf.multiply(eps, tf.ones(shape=(self.division, self.dim_in), dtype=tf.dtypes.float32)))
        self.params = (alpha, beta, gamma)
        self.A = tf.constant(tf.eye(self.dim_out, self.dim_in, dtype=tf.dtypes.float32))
        self.function = function
        self.d_function = d_function
        self.t = np.linspace(0., self.max_time, self.division)

    def call(self, x0):
        def func(t, x, params, A, function, dim_in, dim_out, division):
            x = x.astype(np.float32)
            index = int(t * (division - 1))
            if index > division - 1:
                index = -1
            x1 = x.reshape(-1, dim_in + dim_out)[:, :dim_in]
            y1 = tf.add(tf.matmul(x1, tf.transpose(params[1][index])), params[2][index])
            y2 = tf.multiply(params[0][index], function(tf.matmul(x1, tf.transpose(A))))
            return tf.reshape(tf.concat([y1, y2], 1), [-1])

        y0 = np.zeros(shape=(len(x0), self.dim_out), dtype=np.float32)
        solver = solve_ivp(func, (0., self.max_time), np.hstack([x0, y0]).reshape(-1), t_eval=self.t, args=(self.params, self.A, self.function, self.dim_in, self.dim_out, self.division))
        self.x = solver.y.reshape(len(x0), self.dim_in+self.dim_out, -1)[:, :self.dim_in, :].astype(np.float32)
        return solver.y.reshape(len(x0), self.dim_in+self.dim_out, -1)[:, self.dim_in:, -1]

model = NeuralODEModel(1, 1, 1.0, 100, tf.nn.sigmoid, d_sigmoid)
opt = tf.keras.optimizers.SGD()
loss = tf.keras.losses.MeanSquaredError()
train_loss = tf.keras.metrics.Mean()
test_loss = tf.keras.metrics.Mean()
n_data = 10000
batch_size = 32
epochs = 1000
x, y = get_dataset(n_data)
x_train, x_val, y_train, y_val = train_test_split(x, y, test_size=0.2)

def gradient(model, x0, y_true):
    def func(t, a, params, A, function, bT, x, division):
        a = a.astype(np.float32)
        index = int(t * (division - 1))
        if index < 0:
            index = 0
        a1 = a.reshape(-1, model.dim_in)
        a1 = tf.multiply(-1., tf.add(tf.matmul(a1, params[1][index]), tf.matmul(tf.multiply(bT, tf.multiply(params[0][index], function(tf.matmul(x[:, :, index], tf.transpose(A))))), A)))
        return tf.reshape(a1, [-1])

    with tf.GradientTape() as tape:
        y_pred = tf.Variable(model(x0))
        error = loss(y_true, y_pred)
    bT = tf.cast(tape.gradient(error, y_pred), tf.dtypes.float32)
    aT = np.zeros_like(x0)
    solver = solve_ivp(func, (model.max_time, 0.), aT.reshape(-1), t_eval=model.t[::-1], args=(model.params, model.A, model.d_function, bT, model.x, model.division))
    a = solver.y.reshape(-1, model.dim_in, model.division)[:, :, ::-1]
    g_alpha = tf.einsum('kj,kji->ij', bT, model.function(tf.einsum('jl,ilk->ijk', model.A, model.x)))
    g_beta = tf.einsum('lji,lki->ijk', a, model.x)
    g_gamma = tf.einsum('kji->ij', a)
    return (g_alpha, g_beta, g_gamma)

@tf.function
def train_step(x, y):
    opt.apply_gradients(zip(gradient(model, x, y), model.params))
    error = loss(y, model(x))
    train_loss(error)

@tf.function
def test_step(x, y):
    y_pred = model(x)
    error = loss(y, y_pred)
    test_loss(error)

for epoch in range(epochs):
    x_train, y_train = shuffle(x_train, y_train)
    for i in range(0, len(x_train), batch_size):
        train_step(x_train[i:i+batch_size], y_train[i:i+batch_size])
    for i in range(0, len(x_val), batch_size):
        test_step(x_val[i:i+batch_size], y_val[i:i+batch_size])

    print("Epoch:{}  Train loss:{:.5f}  Test loss:{:.5f}".format(epoch+1, train_loss.result(), test_loss.result()))
    train_loss.reset_states()
    test_loss.reset_states()

公式ドキュメントを参考に構築してみましたが、以下のようなエラーが発生しております。
numpy配列とTensorが混在していることがエラーの原因だと思っているのですが、エラーの原因となる部分が分かりません。解決方法が分かる方いましたら、よろしくお願いいたします。

発生している問題・エラーメッセージ

---------------------------------------------------------------------------
NotImplementedError                       Traceback (most recent call last)
<ipython-input-549-a0b0dde6b671> in <module>()
      3     x_train, y_train = shuffle(x_train, y_train)
      4     for i in range(0, len(x_train), batch_size):
----> 5         train_step(x_train[i:i+batch_size], y_train[i:i+batch_size])
      6 

NotImplementedError: in converted code:

    <ipython-input-546-97616dd16c85>:3 train_step  *
        opt.apply_gradients(zip(gradient(model, x, y), model.params))
    <ipython-input-545-3763226feeb1>:14 gradient  *
        y_pred = tf.Variable(model(x0))
    c:\program files\python36\lib\site-packages\tensorflow_core\python\keras\engine\base_layer.py:778 __call__
        outputs = call_fn(cast_inputs, *args, **kwargs)
    <ipython-input-543-1184e5d2471c>:31 call  *
        solver = solve_ivp(func, (0., self.max_time), np.hstack([x0, y0]).reshape(-1), t_eval=self.t, args=(self.params, self.A, self.function, self.dim_in, self.dim_out, self.division))
    <__array_function__ internals>:6 hstack

    c:\program files\python36\lib\site-packages\numpy\core\shape_base.py:338 hstack
        arrs = atleast_1d(*tup)
    <__array_function__ internals>:6 atleast_1d

    c:\program files\python36\lib\site-packages\numpy\core\shape_base.py:67 atleast_1d
        ary = asanyarray(ary)
    c:\program files\python36\lib\site-packages\numpy\core\_asarray.py:138 asanyarray
        return array(a, dtype, copy=False, order=order, subok=True)
    c:\program files\python36\lib\site-packages\tensorflow_core\python\framework\ops.py:728 __array__
        " array.".format(self.name))

    NotImplementedError: Cannot convert a symbolic Tensor (neural_ode_model_23/Cast:0) to a numpy array.
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

まだ回答がついていません

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.11%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる