Эта статья представляет собой заметку для автора, чтобы изучить TensorFlow2.0 (далее именуемый TF2.0), а используемый учебник — «Практическое глубокое обучение» (версия TF2.0).
Причина, по которой мы можем использовать TensorFlow для реализации линейной регрессии, заключается в том, что мы можем думать о линейной регрессии как о полностью связанной сети только с одним слоем и одним нейроном:
Приведенный выше график представляет собой линейную регрессиюпредставление нейронной сети.
реализовать линейную регрессию
Для реализации линейной регрессии нам нужно
- Определение модели линейной регрессии
- Определите функцию потерь
- Определите итеративный алгоритм оптимизации
Это также основные моменты теории машинного обучения, которые мы можем рассмотреть в этой статье.
Определение модели линейной регрессии
Чтобы реализовать алгоритм, нам сначала нужно выразить его векторным выражением, то есть: использовать векторы и матрицы для описания модели. Преимущество этого заключается в том, что векторный пакетный расчет выполняется намного быстрее, чем расчет каждой выборки в цикле.Векторное выражение для линейной регрессии:
в,Являетсяразмерная матрица,представляет n выборок,Представляет размер объекта;являются параметрами модели, эторазмерный вектор;значение смещения, которое является скаляром;является прогнозируемым значением для n выборок, оно такжевектор.
Модель реализована в TF2.0 следующим образом:
import tensorflow as tf
import numpy as np
import random
def linear_reg(X, w, b):
# matmul 是矩阵乘法
return tf.matmul(X, w) + b
Определите функцию потерь
Как правило, функция потерь регрессионной модели — это MSE (среднеквадратичная ошибка):
В приведенной выше формуленаблюдаемое значение образца (наблюдаемое значение),иобаВектор n представляет собой среднее значение потерь n выборок, чтобы избежать влияния количества выборок на потери. Поскольку Loss является скаляром, приведенную выше формулу также необходимо скорректировать следующим образом:
Потеря реализована с TF2.0 следующим образом:
def squared_loss(y, y_hat, n):
y_observed = tf.reshape(y, y_hat.shape)
return tf.matmul(tf.transpose(y_observed - y_hat),
y_observed - y_hat) / 2 / n
Определите итеративный алгоритм оптимизации
Глубокое обучение в основном использует алгоритм оптимизации минипакетного стохастического градиентного спуска (минипакетный стохастический градиентный спуск) для повторения параметров модели, что может сэкономить место в памяти, увеличить количество итераций модели и ускорить скорость сходимости модели.
Алгоритм SGD каждый раз случайным образом выбирает часть данных из выборки, например, 100 фрагментов данных каждый раз, затем вычисляет потери этих 100 фрагментов данных, вычисляет градиент в соответствии с потерями, а затем использует градиент для обновить текущие параметры, поэтому здесь есть 3 шага. :
- Выборки случайным образом, n каждый раз
- Рассчитайте потери этих n выборок, рассчитайте градиент и используйте градиент для обновления параметров.
- Петли 1 и 2
Давайте сначала посмотрим на код для случайного выбора образцов
def data_iter(features, labels, mini_batch):
'''
数据迭代函数
Args:
- features: 特征矩阵 nxd 维
- labels: 样本,nx1 维
- mini_batch: 每次抽取的样本数
Example:
>>> mini_batch = 100
>>> for X, y in data_iter(features, labels, mini_batch):
>>> # do gradient descent
'''
features = np.array(features)
labels = np.array(labels)
indeces = list(range(len(features)))
random.shuffle(indeces)
for i in range(0, len(indeces), mini_batch):
j = np.array(indeces[i:min(i+mini_batch, len(features))])
yield features[j], labels[j]
Далее давайте посмотрим на код, который обновляет параметры модели:
def sgd(params, lr):
'''
计算梯度,并更新模型参数
Args:
- params: 模型参数,本例中为 [w, b]
- lr: 学习率 learning rate
'''
for param in params:
param.assign_sub(lr * t.gradient(l, param))
Выше код клавиши готов, давайте свяжем их вместе:
# 产生模拟数据
# 1000 条样本,2 维特征
num_samples = 1000
num_dim = 2
# 真实的 weight, bias
w_real = [2, -3.4]
b_real = 4.2
# 产生特征,符合正态分布,标准差为 1
features = tf.random.normal((num_samples, num_dim), stddev=1)
labels = features[:,0]*w_real[0] + features[:,1]*w_real[1] + b_real
# 给 labels 加上噪声数据
labels += tf.random.normal(labels.shape, stddev=0.01)
# 学习率,迭代次数
lr = 0.03
num_epochs = 3
# 初始化模型参数
w = tf.Variable(tf.random.normal([num_dim, 1], stddev=0.01))
b = tf.Variable(tf.zeros(1,))
mini_batch = 10
# 开始训练
for i in range(num_epochs):
for X, y in data_iter(features, labels, mini_batch):
# 在内存中记录梯度过程
with tf.GradientTape(persistent=True) as t:
t.watch([w, b])
# 计算本次小批量的 loss
l = squared_loss(y, linear_reg(X, w, b), mini_batch)
# 计算梯度,更新参数
sgd([w, b], lr)
# 计算本次迭代的总误差
train_loss = squared_loss(labels, linear_reg(features, w, b), len(features))
print('epoch %d, loss %f' % (i + 1, tf.reduce_mean(train_loss)))
Простая реализация
Приведенный выше код реализован шаг за шагом в соответствии с принципом линейной регрессии.Этапы очень понятны, но относительно громоздки.На самом деле, TF предоставляет вам богатую библиотеку алгоритмов для вызова, что значительно повышает эффективность вашей работы. Давайте заменим приведенный выше код методами, предоставленными в библиотеке TF.
Давайте сначала используем keras для определения полностью связанной сетевой структуры только с 1 слоем, Здесь вам не нужно указывать какие-либо параметры:
from tensorflow import keras
from tensorflow.keras import layers
from tensorflow import initializers as init
model = keras.Sequential()
model.add(layers.Dense(1, kernel_initializer=init.RandomNormal(stddev=0.01)))
Затем установите функцию Loss на MSE:
from tensorflow import losses
loss = losses.MeanSquaredError()
Установите стратегию оптимизации на SGD:
from tensorflow.keras import optimizers
trainer = optimizers.SGD(learning_rate=0.03)
Код для случайного получения набора данных небольшими партиями выглядит следующим образом:
from tensorflow import data as tfdata
batch_size = 10
dataset = tfdata.Dataset.from_tensor_slices((features, labels))
dataset = dataset.shuffle(len(features)).batch(batch_size)
Видно, что построение модели заключается в установке некоторых элементов конфигурации без написания какой-либо логики.Объедините вышеприведенные коды следующим образом:
from tensorflow import data as tfdata
from tensorflow import keras
from tensorflow.keras import layers
from tensorflow import initializers as init
from tensorflow import losses
from tensorflow.keras import optimizers
# 设置网络结构:1 层全连接,初始化模型参数
model = keras.Sequential()
model.add(layers.Dense(1, kernel_initializer=init.RandomNormal(stddev=0.01)))
# loss 函数:MSE
loss = losses.MeanSquaredError()
# 优化策略:随机梯度下降
trainer = optimizers.SGD(learning_rate=0.03)
# 设置数据集,和小批量的样本数
batch_size = 10
dataset = tfdata.Dataset.from_tensor_slices((features, labels))
dataset = dataset.shuffle(len(features)).batch(batch_size)
num_epochs = 3
for epoch in range(1, num_epochs+1):
# 取小批量进行计算
for (batch, (X, y)) in enumerate(dataset):
with tf.GradientTape() as tape:
# 计算 loss
l = loss(model(X, training=True), y)
# 计算梯度并更新参数
grads = tape.gradient(l, model.trainable_variables)
trainer.apply_gradients(zip(grads, model.trainable_variables))
# 本次迭代后的总 loss
l = loss(model(features), labels)
print('epoch %d, loss: %f' % (epoch, l.numpy().mean()))
# 输出模型参数
print(model.get_weights())
Приведенный выше код можно напрямую скопировать и запустить (зависимую библиотеку необходимо установить самостоятельно), и новички могут попробовать его.
резюме
В этой статье реализована простая модель линейной регрессии через TF2.0, включая
- По основным шагам определения модели, определения функции потерь и определения итерационного алгоритма реализуется обобщенная нейронная сеть, воробей хоть и маленький, но имеет все внутренние органы.
- Реализуйте упрощенную версию с использованием богатых компонентов TF2.0, направленных на понимание использования TF2.0.
Ссылаться на: