Определения подклассов моделей TensorFlow с настраиваемыми скрытыми слоями

Я изучаю определения подклассов Models в TensorFlow.

Довольно простое определение будет примерно таким

class MyNetwork1(tf.keras.Model):
    def __init__(self, num_classes = 10):
        super().__init__()
        self.num_classes = num_classes
    
        self.input_layer = tf.keras.layers.Flatten()
        self.hidden_1 = tf.keras.layers.Dense(128, activation = 'relu')
        self.hidden_2 = tf.keras.layers.Dense(64, activation = 'relu')
        self.output_layer = tf.keras.layers.Dense(self.num_classes, activation = 'softmax')
    
    def call(self, input_tensor):
        x = self.input_layer(input_tensor)
        x = self.hidden_1(x)
        x = self.hidden_2(x)
        x = self.output_layer(x)
        
        return x

После построения модели,

Model1 = MyNetwork1()
Model1.build((None, 28, 28, 1))

Это будет выглядеть

Model: "my_network1"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
flatten (Flatten)            multiple                  0         
_________________________________________________________________
dense (Dense)                multiple                  100480    
_________________________________________________________________
dense_1 (Dense)              multiple                  8256      
_________________________________________________________________
dense_2 (Dense)              multiple                  650       
=================================================================
Total params: 109,386
Trainable params: 109,386
Non-trainable params: 0

Поскольку этот метод не может настроить количество нейронов и тип активации для каждого слоя, я попытался немного его отредактировать.

Я пробовал следующее определение

class MyNetwork2(tf.keras.Model):
    
    def __init__(self, num_classes = 2, hidden_dimensions = [100], 
                  hidden_activations = ['relu']):
        super().__init__()
        self.inputlayer = tf.keras.layers.Flatten()
        i = 0
        self.hidden_layers = []
        
        for d,a in zip(hidden_dimensions,hidden_activations):
            i += 1
            setattr(self, 'hidden_' + str(i) , 
                    tf.keras.layers.Dense(d, activation = a))
            self.hidden_layers.append('self.hidden_' + str(i) + '(x)')
            
        self.outputlayer = tf.keras.layers.Dense(num_classes, activation = 'softmax')
        self.num_layers = len(hidden_dimensions) + 2
        
    def call(self, inputtensor):
        
        x = self.inputlayer(inputtensor)
        
        for h in self.hidden_layers:
            # print(h)
            x = eval(h,{}, x)
            
        x = self.outputlayer(x)
        
        return x

В этом коде я попытался сделать то же самое, что и в предыдущем определении.

Model2 = MyNetwork2(num_classes = 10, hidden_dimensions = [128,64], 
                        hidden_activations = ['relu', 'relu'])

Model2.build((None, 28, 28, 1))

Однако я столкнулся со следующей ошибкой:

TypeError: Only integers, slices (`:`), ellipsis (`...`), tf.newaxis (`None`) and scalar tf.int32/tf.int64 tensors are valid indices, got 'self'

Как я могу исправить эту ошибку, чтобы достичь своей цели?

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
0
283
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Кажется, что это очень сложный способ сделать что-то. Если вы используете словарь для переменного количества слоев вместо eval, все работает нормально.

class MyNetwork2(tf.keras.Model):
    def __init__(self, num_classes=2, hidden_dimensions=[100],
                 hidden_activations=['relu']):
        super(MyNetwork2, self).__init__()
        self.inputlayer = tf.keras.layers.Flatten()
        self.hidden_layers = dict()

        for i, (d, a) in enumerate(zip(hidden_dimensions, hidden_activations)):
            self.hidden_layers['hidden_'+str(i)]=tf.keras.layers.Dense(d, activation=a)

        self.outputlayer = tf.keras.layers.Dense(num_classes, activation='softmax')
        self.num_layers = len(hidden_dimensions) + 2

Пример запуска:

import tensorflow as tf
import numpy as np


class MyNetwork2(tf.keras.Model):
    def __init__(self, num_classes=2, hidden_dimensions=[100],
                 hidden_activations=['relu']):
        super(MyNetwork2, self).__init__()
        self.inputlayer = tf.keras.layers.Flatten()
        self.hidden_layers = dict()

        for i, (d, a) in enumerate(zip(hidden_dimensions, hidden_activations)):
            self.hidden_layers['hidden_'+str(i)]=tf.keras.layers.Dense(d, activation=a)

        self.outputlayer = tf.keras.layers.Dense(num_classes, activation='softmax')
        self.num_layers = len(hidden_dimensions) + 2

    def call(self, inputtensor, training=None, **kwargs):

        x = self.inputlayer(inputtensor)
        for k, v in self.hidden_layers.items():
            x = v(x)

        x = self.outputlayer(x)

        return x

Model2 = MyNetwork2(num_classes = 10, hidden_dimensions = [128,64],
                        hidden_activations = ['relu', 'relu'])

Model2.build((None, 28, 28, 1))

Model2(np.random.uniform(0, 1, (1, 28, 28, 1)).astype(np.float32))
<tf.Tensor: shape=(1, 10), dtype=float32, numpy=
array([[0.14969216, 0.10196744, 0.0874036 , 0.08350615, 0.18459582,
        0.07227989, 0.08263624, 0.08537506, 0.10291573, 0.04962786]],
      dtype=float32)>

Скрытые слои как словарь:

Model2.hidden_layers
{'hidden_0': <tensorflow.python.keras.layers.core.Dense at 0x1891b5c13a0>,
 'hidden_1': <tensorflow.python.keras.layers.core.Dense at 0x1891b5c1d00>}

Действительно хорошее решение. ценю вашу помощь. Не могли бы вы сказать мне, что именно не так с моим решением eval, чтобы избежать его в будущем?

Omar Ayman 21.12.2020 18:39

Я не очень хорошо знаком с использованием eval, особенно в контексте графа Tensorflow, поэтому не думаю, что смогу здесь чем-то помочь.

Nicolas Gervais 21.12.2020 18:43

Другие вопросы по теме