Как можно создать нейронную сеть с одинаковыми весами для разных узлов в одном и том же слое?

Вопрос или проблема

Структура, которую я себе представляю, похожа на ту, что на изображении ниже

введите описание изображения здесь

где на выходе используется softmax. Для скрытого слоя у нас было бы

$$Z_1 = W_{11}^{[1]}x_2 + W_{12}^{[1]}x_2$$
$$Z_2 = W_{21}^{[1]}x_2 + W_{22}^{[1]}x_2$$
$$Z_3 = W_{11}^{[1]}x_3 + W_{12}^{[1]}x_4$$
$$Z_4 = W_{21}^{[1]}x_3 + W_{22}^{[1]}x_4$$

такой же принцип применим к softmax. Я пришел к этой идее, пытаясь создать нейронную сеть, которая бы вела себя похоже на условную логистическую регрессию (https://en.wikipedia.org/wiki/Conditional_logistic_regression).

Я сделал реализацию с помощью Keras и Tensorflow, которая, как я полагаю, будет вести себя так, как надо, но я не уверен.

class ConditionalNN(tf.keras.Model):
  def __init__(self, out_dim, l1 = 0, l2 = 0):
    super(ConditionalNN, self).__init__(name="")
    self.layer1 = tf.keras.layers.Dense(20,'tanh',kernel_regularizer=tf.keras.regularizers.l1_l2(l1=l1, l2=l2))
    self.layerL1 = tf.keras.layers.Dense(1,'linear',kernel_regularizer=tf.keras.regularizers.l1_l2(l1=l1, l2=l2))
    self.layerL2 = tf.keras.layers.Softmax(axis=-2)
  def call(self, input_tensor, training=False):
    x = self.layer1(input_tensor,training=training)
    x = self.layerL1(x,training=training)
    x = self.layerL2(x,training=training)
    return x

В этом случае входными данными будет 3D-тензор, например:

X = [
        [[x1,x2],
         [x3,x4]],
           ...
    ]

а выход будет чем-то вроде:

Y = [[1,0],
     [0,1],
     [1,0],
      ...
    ]

Это интересная идея, и я думаю, имеет смысл делиться весами. Я не видел точно того, что вы описали, но обычно делятся весами в случаях, когда два входа имеют схожий смысл. Например, в этой статье они используют общие векторы эмбеддинга для целевого видео и видео из истории пользователя, у которых одинаковый video_id. Это определенно возможно реализовать в TensorFlow, если два входа имеют одинаковые размеры. Способ реализации очевиден: создайте матрицу весов с размерами (feature_dimension, num_neuron) и умножьте разные входы на одну и ту же матрицу.

Ответ или решение

Создание нейронной сети с одинаковыми весами для различных узлов в одном слое представляет собой интересную задачу, особенно учитывая ваше сравнение с условной логистической регрессией. Рассмотрим, как можно реализовать такую архитектуру с помощью TensorFlow и Keras, а также обсудим теоретические аспекты, лежащие в основе этого подхода.

Понимание концепции общего веса

Ваша идея о том, что некоторые узлы в скрытом слое могут делить одни и те же веса, может быть полезна в случаях, когда различные входные данные имеют схожие характеристики или требуют применения одних и тех же признаков. Это может помочь в обучении модели, так как она будет более универсальной и сможет лучше адаптироваться к различным входным данным.

Построение модели

Для реализации такой модели вам нужно следующее:

  1. Определение структуры сети: Вам потребуется слой, который будет использовать одинаковые веса для нескольких узлов. Это можно сделать с помощью кастомной функции вызова, которая будет применять один и тот же набор весов к различным входным данным.

  2. Создание общей весовой матрицы: Ваша задача будет заключаться в создании матрицы весов с размерностью, соответствующей размеру признаков и количеству нейронов в вашем слое.

  3. Использование TensorFlow/Keras: Вы можете задать веса в TensorFlow, используя подходы, применяемые в Keras. Например, вы можете создать массив весов в конструкторе класса и использовать его в функции call.

Пример реализации

import tensorflow as tf

class ConditionalNN(tf.keras.Model):
    def __init__(self, out_dim, l1=0, l2=0):
        super(ConditionalNN, self).__init__(name="")
        self.shared_weights = tf.keras.layers.Dense(20, activation='tanh', 
                                                     kernel_regularizer=tf.keras.regularizers.l1_l2(l1=l1, l2=l2))
        self.output_layer = tf.keras.layers.Dense(out_dim, activation='softmax',
                                                   kernel_regularizer=tf.keras.regularizers.l1_l2(l1=l1, l2=l2))

    def call(self, inputs, training=False):
        # Предполагаем, что inputs имеет вид [batch_size, num_samples, feature_dim]
        # Применяем общий весовой слой
        shared_output = self.shared_weights(inputs)
        # Объединяем выводы для получения конечных результатов
        outputs = self.output_layer(shared_output)
        return outputs

# Пример входных данных
X = tf.random.normal(shape=(batch_size, num_samples, feature_dimension))
model = ConditionalNN(out_dim=2)
output = model(X)

Ключевые моменты

  • Единая весовая матрица: Все узлы в одном слое применяют одну и ту же матрицу весов shared_weights, что позволяет объявлять веса один раз и использовать их для различных входных сигналов.

  • Соглашение о размерностях: Важно, чтобы ваши входные данные имели совместимые размерности, чтобы избежать ошибок при матричных умножениях.

  • Значение softmax: На выходе, применение функции активации softmax обеспечивает нормализованные вероятностные оценки, которые могут быть использованы для многоклассовой классификации.

Заключение

Использование одинаковых весов для разных узлов в одном слое является мощным инструментом при разработке нейронных сетей. Это может способствовать более эффективному обучению и лучшему обобщению модели. Надеюсь, представленная информация окажется полезной для вас в реализации задуманной архитектуры и достижения ваших целей в области машинного обучения и анализа данных.

Оцените материал
Добавить комментарий

Капча загружается...