1. Объяснить и реализовать линейный слой
Линейный слой в глубоком обучении — это слой, который выполняет линейную комбинацию входных данных и применяет термин смещения.
В этой реализации параметры input_dim и output_dim задают количество входных и выходных единиц соответственно для слоя. Параметр смещения — это логическое значение, которое определяет, должен ли слой иметь член смещения или нет. Веса инициализируются случайным образом с использованием распределения Гаусса, а смещение инициализируется равным нулю. Прямой метод вычисляет линейную комбинацию входных данных и применяет член смещения, если он указан.
import numpy as np class Linear: def __init__(self, input_dim, output_dim, bias=True): self.input_dim = input_dim self.output_dim = output_dim self.bias = bias self.weights = np.random.randn(input_dim, output_dim) if self.bias: self.bias = np.zeros((1, output_dim)) def forward(self, x): out = np.dot(x, self.weights) if self.bias: out += self.bias return out
2. Объясните и осознайте сигмовидную активацию
Сигмовидная функция активации — популярная функция активации, используемая во многих моделях глубокого обучения. Он отображает любой ввод в диапазоне от 0 до 1, что делает его полезным для задач бинарной классификации.
В этой реализации функция принимает входные данные x и возвращает сигмовидную активацию. Сигмовидная активация вычисляется путем применения экспоненциальной функции np.exp к отрицательному входному значению x, а затем взятия обратной суммы 1 и результата. Результирующее значение всегда находится в диапазоне от 0 до 1 включительно.
import numpy as np def sigmoid(x): return 1 / (1 + np.exp(-x))
3. Объясните и реализуйте вывод потерь l2 и график его вычислений.
Потеря L2, также известная как среднеквадратическая ошибка (MSE), является популярной функцией потерь, используемой для задач регрессии. Он измеряет разницу между прогнозируемым выходом и истинным выходом путем вычисления суммы квадратов разностей и деления на количество выборок.
В этой реализации функция принимает два входа: y_true и y_pred. y_true — это истинный результат, а y_pred — прогнозируемый результат. Сначала функция вычисляет разницу между y_true и y_pred, используя поэлементное вычитание. Затем он возводит разницу в квадрат и вычисляет сумму по всем образцам. Наконец, он делит сумму на количество выборок n, чтобы вычислить среднеквадратичную ошибку. Полученное значение представляет собой потери L2, которые можно использовать для оценки производительности модели.
import numpy as np def l2_loss(y_true, y_pred): n = y_true.shape[0] loss = np.sum((y_true - y_pred)**2) / n return loss
4. Объясните и реализуйте передачу вперед и назад.
В глубоком обучении прямой проход относится к процессу вычисления выходных данных нейронной сети с учетом входных данных. Обратный проход, также известный как обратное распространение, относится к процессу вычисления градиентов потерь по отношению к параметрам модели, которые затем используются для обновления параметров модели.
Вот простой пример прямого прохода и обратного прохода для нейронной сети с одним линейным слоем и сигмовидной функцией активации, за которой следует функция потери среднеквадратичной ошибки.
В этом примере функция forward_pass принимает входные данные x, истинные выходные данные y_true и линейный слой linear и возвращает предсказанные выходные данные y_pred и среднеквадратичную ошибку потерь. Функция back_pass принимает входные данные x, истинные выходные данные y_true, предсказанные выходные данные y_pred и линейный слой linear и возвращает градиенты потерь относительно входных данных линейного слоя d_linear, весов d_weights и смещения.
import numpy as np def sigmoid(x): return 1 / (1 + np.exp(-x)) def l2_loss(y_true, y_pred): n = y_true.shape[0] loss = np.sum((y_true - y_pred)**2) / n return loss class Linear: def __init__(self, input_dim, output_dim, bias=True): self.input_dim = input_dim self.output_dim = output_dim self.bias = bias self.weights = np.random.randn(input_dim, output_dim) if self.bias: self.bias = np.zeros((1, output_dim)) def forward(self, x): out = np.dot(x, self.weights) if self.bias: out += self.bias return out def forward_pass(x, y_true, linear, activation=sigmoid): y_pred = activation(linear.forward(x)) loss = l2_loss(y_true, y_pred) return y_pred, loss def backward_pass(x, y_true, y_pred, linear): d_y_pred = 2 * (y_pred - y_true) / x.shape[0] d_linear = np.dot(d_y_pred, linear.weights.T) d_weights = np.dot(x.T, d_y_pred) d_bias = np.sum(d_y_pred, axis=0, keepdims=True) return d_linear, d_weights, d_bias # Example usage input_dim = 10 output_dim = 1 x = np.random.randn(100, input_dim) y_true = np.random.randn(100, output_dim) linear = Linear(input_dim, output_dim) y_pred, loss = forward_pass(x, y_true, linear) d_linear, d_weights, d_bias = backward_pass(x, y_true, y_pred, linear)
5. Что такое исчезновение градиента, какие методы могут решить эту проблему (активация xavier, пакетная норма, остаточный блок, relu вместо сигмовидной и т. д.)
Исчезновение градиента — это явление, которое может происходить в глубоких нейронных сетях, где градиенты параметров по отношению к потерям становятся очень малыми в процессе обратного распространения, что затрудняет обновление параметров оптимизатором. Это может привести к медленной сходимости или даже к невозможности сходимости.
Существует несколько методов решения проблемы исчезновения градиента в глубоких нейронных сетях, в том числе:
- Функции активации. Использование функций активации, таких как ReLU, дырявый ReLU или ELU, может помочь справиться с исчезновением градиента, поскольку они имеют ненулевые градиенты для положительных входных данных.
- Пакетная нормализация. Пакетная нормализация нормализует активации каждого слоя в пакете, что помогает предотвратить слишком большое или слишком малое количество активаций.
- Пропустить/Остаточные соединения: Пропустить соединения позволяют градиентам обходить один или несколько слоев и переходить непосредственно от вывода к более ранним слоям в сети, что может помочь предотвратить исчезновение градиента.
- Отсечение градиента: Отсечение градиента — это метод, который ограничивает величину градиентов, что может помочь предотвратить их слишком большой размер и взрыв.
- Инициализация весов: правильная инициализация весов сети может помочь предотвратить исчезновение градиента, так как малые значения веса могут привести к тому, что градиенты станут маленькими.
Вот пример реализации нейронной сети с активацией ReLU и пакетной нормализацией на Python:
import numpy as np def relu(x): return np.maximum(0, x) def l2_loss(y_true, y_pred): n = y_true.shape[0] loss = np.sum((y_true - y_pred)**2) / n return loss class Linear: def __init__(self, input_dim, output_dim, bias=True): self.input_dim = input_dim self.output_dim = output_dim self.bias = bias self.weights = np.random.randn(input_dim, output_dim) if self.bias: self.bias = np.zeros((1, output_dim)) def forward(self, x): out = np.dot(x, self.weights) if self.bias: out += self.bias return out ''' In this example, the BatchNorm class implements batch normalization. The forward method takes an input x and a boolean training flag, and returns the normalized output. If the training flag is True, the method computes the mean and variance of the mini-batch and updates the running mean and variance. If the training flag is False, the method uses the running mean and variance to normalize the input. The beta and gamma parameters can be learned during training to adjust ''' class BatchNorm: def __init__(self, num_features, epsilon=1e-5, momentum=0.9): self.num_features = num_features self.epsilon = epsilon self.momentum = momentum self.running_mean = np.zeros(num_features) self.running_var = np.zeros(num_features) self.gamma = np.ones(num_features) self.beta = np.zeros(num_features) def forward(self, x, training=True): if training: mean = x.mean(axis=0) var = x.var(axis=0) self.running_mean = self.momentum * self.running_mean + (1 - self.momentum) * mean self.running_var = self.momentum * self.running_var + (1 - self.momentum) * var x_hat = (x - mean) / np.sqrt(var + self.epsilon) else: x_hat = (x - self.running_mean) / np.sqrt(self.running_var + self.epsilon) out = self.gamma * x_hat + self.beta return out
6. Что такое оценка максимального правдоподобия,Как ее реализовать,Как она связана с градиентным спуском
Оценка максимального правдоподобия (MLE) — это распространенный метод, используемый в статистическом моделировании и машинном обучении для оценки параметров модели, которые лучше всего объясняют наблюдаемые данные. В MLE цель состоит в том, чтобы найти значения параметров, которые максимизируют функцию правдоподобия, которая представляет вероятность наблюдения данных с заданными параметрами.
MLE можно рассматривать как задачу оптимизации, целью которой является максимизация функции правдоподобия по отношению к параметрам. Одним из распространенных способов решения этой задачи оптимизации является градиентный спуск, при котором градиент функции правдоподобия по отношению к параметрам вычисляется и используется для обновления параметров в направлении максимального правдоподобия.
Вот простой пример того, как MLE можно реализовать в Python для оценки параметров распределения Гаусса:
В этом примере функция Гаусса вычисляет функцию плотности вероятности распределения Гаусса. Функция правдоподобия вычисляет вероятность данных с заданными параметрами. Функции grad_mu и grad_sigma вычисляют градиент вероятности по отношению к среднему и стандартному отклонению соответственно. Функция MLE реализует алгоритм MLE с использованием градиентного спуска. Функция обновляет среднее значение и стандартное отклонение на каждой итерации, пока не будет достигнуто максимальное количество итераций или не будут выполнены критерии сходимости.
import numpy as np def gaussian(x, mu, sigma): return np.exp(-(x - mu)**2 / (2 * sigma**2)) / (np.sqrt(2 * np.pi) * sigma) def likelihood(x, mu, sigma): return np.prod(gaussian(x, mu, sigma)) def grad_mu(x, mu, sigma): return np.sum((x - mu) * gaussian(x, mu, sigma)) / sigma**2 def grad_sigma(x, mu, sigma): return np.sum(((x - mu)**2 / sigma**2 - 1) * gaussian(x, mu, sigma)) / (2 * sigma) def MLE(x, mu, sigma, learning_rate=0.01, max_iter=100): for i in range(max_iter): grad_mu_val = grad_mu(x, mu, sigma) grad_sigma_val = grad_sigma(x, mu, sigma) mu = mu + learning_rate * grad_mu_val sigma = sigma + learning_rate * grad_sigma_val if i % 10 == 0: print(f"Iteration {i}: mu = {mu:.4f}, sigma = {sigma:.4f}, likelihood = {likelihood(x, mu, sigma):.4f}") return mu, sigma # Example usage np.random.seed(0) data = np.random.normal(0, 1, 100) mu, sigma = MLE(data, 0, 1) print(f"Estimated mu: {mu:.4f}") print(f"Estimated sigma: {sigma:.4f}")
7. В чем разница между Batchnorm, layernorm и instancenorm? Как их реализовать?
Пакетная нормализация (BatchNorm), нормализация уровня (LayerNorm) и нормализация экземпляра (InstanceNorm) — все это методы нормализации, используемые в глубоком обучении для нормализации активаций сети перед применением функции активации. Основное различие между этими методами нормализации заключается в способе нормализации активаций и количестве параметров нормализации.
BatchNorm нормализует активации мини-партии путем вычитания среднего значения и деления на стандартное отклонение. BatchNorm имеет два обучаемых параметра для каждой активации: параметр масштаба (гамма) и параметр сдвига (бета). Эти параметры используются для масштабирования и сдвига нормализованных активаций, позволяя сети изучить оптимальные параметры нормализации.
LayerNorm нормализует активации всех нейронов в одном слое, а не в мини-пакете. Это делает LayerNorm более стабильным по сравнению с BatchNorm, поскольку статистика нормализации меньше зависит от размера мини-пакета. Как и BatchNorm, LayerNorm также имеет два обучаемых параметра для каждой активации.
InstanceNorm нормализует активацию каждого отдельного экземпляра или точки данных, а не мини-пакета или слоя. Это делает InstanceNorm хорошо подходящим для передачи стиля изображения, когда нормализация выполняется для каждого изображения, а не для пакета изображений. В отличие от BatchNorm и LayerNorm, InstanceNorm не имеет обучаемых параметров.
# Here's an example of how to implement BatchNorm in Python using the keras library: from keras.layers import BatchNormalization model.add(BatchNormalization()) # here's an example of how to implement LayerNorm in Python using the tensorflow library: import tensorflow as tf def layer_norm(x): return tf.contrib.layers.layer_norm(x, begin_norm_axis=-1) output = layer_norm(input) # here's an example of how to implement InstanceNorm in Python using the tensorflow library: import tensorflow as tf def instance_norm(x): mean, variance = tf.nn.moments(x, axes=[1, 2], keepdims=True) return tf.divide(tf.subtract(x, mean), tf.sqrt(variance + 1e-5)) output = instance_norm(input)
8. зачем использовать позиционное кодирование во внимании? сколько способов? Каковы плюсы и минусы?
Позиционное кодирование используется в моделях, основанных на внимании, для предоставления модели информации об относительном или абсолютном положении токенов в последовательности. Это особенно полезно для последовательностей переменной длины, таких как предложения или последовательности в НЛП, где модель может по своей природе не понимать порядок или положение токенов.
Существует несколько методов вычисления позиционных кодировок, в том числе:
- Синусоидальные функции: в этом методе позиционные кодировки генерируются путем применения синусоидальных функций к положению маркеров.
- Изученные вложения: в этом методе модель изучает набор вложений специально для позиций токенов во время обучения.
- Фиксированные вложения: в этом методе к вложениям токенов добавляется набор фиксированных вложений для предоставления информации о местоположении.
Плюсы использования позиционных кодировок:
- Улучшенная производительность: позиционное кодирование может помочь повысить производительность моделей на основе внимания при выполнении определенных задач, особенно тех, где важен порядок токенов.
- Гибкость: позиционное кодирование можно добавить к любой модели, основанной на внимании, независимо от ее архитектуры или типа выполняемой задачи.
Минусы использования позиционных кодировок:
- Повышенная сложность: добавление позиционных кодировок может увеличить сложность модели, усложнив ее обучение и потребовав дополнительных вычислительных ресурсов.
- Переобучение: в некоторых случаях модель может слишком сильно полагаться на позиционное кодирование, что приводит к переобучению и снижению производительности на данных вне выборки.
В целом, использование позиционного кодирования в моделях, основанных на внимании, может быть полезным инструментом для повышения производительности при выполнении определенных задач, но важно тщательно взвесить все «за» и «против» и выбрать подходящий метод на основе специфических требований задачи в момент ее выполнения. рука.
примечание: я получил образцы вопросов из Интернета, я внес некоторые изменения в исходный пост.