Q:

How to implement matmul-based nn written in TF1 to TF2

I want to implement simple, matmul-based neural network written in TF1 to TF2.
Here is source. (don't mind Korean comments, it's tutorial written in Korean)
So I found 'how to migrate TF1 into TF2', and I know I have to remove placeholders.
Here is my code overall:
import tensorflow as tf
import numpy as np

x_data = np.array(
    [[0, 0], [1, 0], [1, 1], [0, 0], [0, 0], [0, 1]])

y_data = np.array([
    [1, 0, 0],
    [0, 1, 0],
    [0, 0, 1],
    [1, 0, 0],
    [1, 0, 0],
    [0, 0, 1]
])

x_data = tf.cast(x_data, tf.float32)
y_data = tf.cast(y_data, tf.float32)

W1 = tf.Variable(tf.random.uniform([2, 10], -1., 1.))
W2 = tf.Variable(tf.random.uniform([10, 3], -1., 1.))
b1 = tf.Variable(tf.zeros([10]))
b2 = tf.Variable(tf.zeros([3]))

Layer1 = tf.matmul(x_data, W1) + b1
Layer1 = tf.nn.relu(Layer1)

model = tf.matmul(Layer1, W2) + b2

cost = tf.reduce_mean(
    tf.nn.softmax_cross_entropy_with_logits(labels=y_data, logits=model)
)
optimizer = tf.keras.optimizers.Adam(learning_rate=0.01)

optimizer.minimize(loss=lambda: cost , var_list=[W1, W2, b1, b2])

I found Issue with AdamOptimizer , and I changed loss to lambda.
And, got this Error:
ValueError: No gradients provided for any variable: ['Variable:0', 'Variable:0', 'Variable:0', 'Variable:0'].

And I have no idea how to fix it.
So I'd like to know proper way to implement something like this in TF2.

A:

All right. I went through official guide for eager execution, and finally done it.
Here's the code:
import tensorflow as tf
import numpy as np

x_data = np.array(
    [[0, 0], [1, 0], [1, 1], [0, 0], [0, 0], [0, 1]])

y_data = np.array([
    [1, 0, 0],
    [0, 1, 0],
    [0, 0, 1],
    [1, 0, 0],
    [1, 0, 0],
    [0, 0, 1]
])

x_data = tf.cast(x_data, tf.float32)
y_data = tf.cast(y_data, tf.float32)

class Model(tf.keras.Model):
    def __init__(self):
        super(Model, self).__init__()
        self.W1 = tf.Variable(tf.random.uniform([2, 10], -1., 1.))
        self.W2 = tf.Variable(tf.random.uniform([10, 3], -1., 1.))
        self.b1 = tf.Variable(tf.zeros([10]))
        self.b2 = tf.Variable(tf.zeros([3]))
    def _calc_layer(x, w, b):
        return tf.matmul(x, w) + b
    def __call__(self, x):
        layer1 = tf.nn.relu(Model._calc_layer(x_data, self.W1, self.b1))
        return Model._calc_layer(layer1, self.W2, self.b2)

def cost(model, inputs, targets):
    return tf.reduce_mean(
        tf.nn.softmax_cross_entropy_with_logits(labels=targets,
                                                logits=model(inputs))
    )

model = Model()

def cost_tominimize():
    return cost(model, x_data, y_data)

optimizer = tf.keras.optimizers.Adam(learning_rate=0.01)

for i in range(100):
    optimizer.minimize(loss=cost_tominimize,
                        var_list=model.trainable_variables)
    #print(cost_tominimize().numpy())

#test
prediction = tf.argmax(model(x_data), 1)
target = tf.argmax(y_data, 1)
print("prediction : ", prediction.numpy())
print("real : ", target.numpy())

is_correct = tf.equal(prediction, target)
accuracy = tf.reduce_mean(tf.cast(is_correct, tf.float32))
print('accuracy: %.2f%%' % (accuracy * 100))

Also there is version which doesn't use class:
import tensorflow as tf
import numpy as np

x_data = np.array(
    [[0, 0], [1, 0], [1, 1], [0, 0], [0, 0], [0, 1]])

y_data = np.array([
    [1, 0, 0],
    [0, 1, 0],
    [0, 0, 1],
    [1, 0, 0],
    [1, 0, 0],
    [0, 0, 1]
])

x_data = tf.cast(x_data, tf.float32)
y_data = tf.cast(y_data, tf.float32)

W1 = tf.Variable(tf.random.uniform([2, 10], -1., 1.))
W2 = tf.Variable(tf.random.uniform([10, 3], -1., 1.))
b1 = tf.Variable(tf.zeros([10]))
b2 = tf.Variable(tf.zeros([3]))

def calc_layer(x, w, b):
    return tf.matmul(x, w) + b

def model(x):
    layer1 = tf.nn.relu(calc_layer(x, W1, b1))
    return calc_layer(layer1, W2, b2)

def cost(model, inputs, targets):
    return tf.reduce_mean(
        tf.nn.softmax_cross_entropy_with_logits(labels=targets,
                                                logits=model(inputs))
    )

def cost_tominimize():
    return cost(model, x_data, y_data)

optimizer = tf.keras.optimizers.Adam(learning_rate = 0.01)

for i in range(100):
    optimizer.minimize(loss=cost_tominimize,
                       var_list = [W1, W2, b1, b2])
    print(cost_tominimize().numpy())

#...and test part here...

