Как статическая полевая инициализация работает в C#?

Я думаю, что предубеждения почти всегда полезны. Фактически, значение смещения позволяет вам переключать функцию активации влево или вправо, что может иметь решающее значение для успешного обучения.

Это может помочь взглянуть на простой пример. Рассмотрим эту 1-входную сеть с 1 выходом, которая не имеет смещения:

simple network [/g0]

Выходной сигнал сети вычисляется путем умножения ввода (x) по весу (w0) и передаче результата через какую-то функцию активации (например, сигмоидальную функцию).

Вот функция, которую эта сеть вычисляет для различных значений w0:

network output, given different w0 weights [/g1]

Изменение веса w0 существенно изменяет «крутизну» сигмоида. Это полезно, но что, если вы хотите, чтобы сеть выводила 0, когда x равно 2? Просто изменение крутизны сигмоида не будет действительно работать - вы хотите, чтобы вы могли сдвинуть всю кривую вправо.

Именно это и позволяет вам сделать смещение. Если мы добавим смещение в эту сеть, например:

simple network with a bias [/g2]

... тогда выход сети станет sig (w0 * x + w1 * 1,0). Вот как выглядит выход сети для разных значений w1:

network output, given different w1 weights [/g3]

Имея вес -5 для w1, сдвигает кривую на справа, что позволяет нам иметь сеть, которая выводит 0, когда x равно 2.

24
задан Prankster 2 April 2009 в 17:38
поделиться

4 ответа

Это корректно.

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

Вот полный путь выполнения:

Когда Вы сначала звоните var a = new A(); в Вашей программе это - первый раз, когда к A получают доступ.

Это исчерпает статическую инициализацию A._A

На данном этапе A. _ конструкции с _A = (new A()).I();

Это совершает нападки


Console.WriteLine("new A()");
if (_A == null)
    Console.WriteLine("_A == null");        

с тех пор в этой точке, _A (еще) не был установлен с возвращенным, созданным типом.

Затем, статический конструктор A { static A(); } выполняется. Это печатает "помехи ()" сообщение.

Наконец, Ваш исходный оператор (var a = new A();) выполняется, но в этой точке, создаются помехи, таким образом, Вы получаете заключительную печать.

28
ответ дан 28 November 2019 в 21:37
поделиться

Кажется, компилятор делает ожидаемое.

1st - весь статический код выполняется (сначала поля, затем статический конструктор) в классе:

public static string _A = (new A()).I();

// and

static A()
{
    Console.WriteLine("static A()");
}

2nd - вызывается конструктор класса:

public A()
{
    Console.WriteLine("new A()");
    if (_A == null)
        Console.WriteLine("_A == null");
    else
        Console.WriteLine("_A == " + _A);
}

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

0
ответ дан bruno conde 28 November 2019 в 21:37
поделиться

Я на самом деле полагаю, что это делает то, что Вы думаете. Ваш тест мешает говорить.

Ваш initalization для _A

public static string _A = (new A()).I();

Сначала создает новый экземпляр A, таким образом Ваши записи новых () и _A = пустой указатель. Поскольку это было пустым, когда это запустилось, поскольку это - инициализация. Однажды initalized, статического конструктора вызывают, который возвращает новый экземпляр.

1
ответ дан 28 November 2019 в 21:37
поделиться

Да, статическая полевая инициализация должна завершиться, прежде чем конструктора вызывают. Но Вы помещаете компилятор в ненормальную ситуацию, и это просто не может соблюсти это правило.

Это - интересный прием, но он не собирается происходить в нормальном приложении.

-1
ответ дан 28 November 2019 в 21:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: