在校正数据上训练全连接的多层神经网络
在这个例子中,我们将考虑基于神经网络模型的数据处理和训练。 将演示滑动窗口方法,将训练和测试样本划分为训练数据集,并确定模型参数以获得最准确的预测值。
启动必要的库:
Pkg.add(["Statistics", "CSV", "Flux", "Optimisers"])
using Statistics
using CSV
using DataFrames
using Flux
using Plots
using Flux: train!
using Optimisers
培训和测试样本的准备:
上传用于训练模型的数据:
df = DataFrame(CSV.File("$(@__DIR__)/data.csv"));
执行示例**/start/examples/data_analysis/data_processing后保存了数据。ipynb**。
训练数据集的形成:
整个数据集分为训练和测试样本。 训练样本为总数据集的0.8,测试样本为0.2。
T = df[1:1460,3]; # определение обучающего набора данных, весь датасет 1825 строк
first(df, 5)
将向量T分成长度为100个观测值的批次:
batch_starts = 1:1:1360 # определение диапазона для цикла
weather_batches = [] # определение пустого массива для записи результатов выполнения цикла
for start in batch_starts
dop = T[start:start+99] # батч на текущем временном шаге
weather_batches = vcat(weather_batches, dop) # запись батча в массив
end
批处理是一个小数据集,可用作构建预测模型的训练集。 取自初始训练集T采用滑动窗方法。
滑动窗口方法:
其中x是观测值,y1是预测值。
将结果集转换为向量字符串:
weather_batches = weather_batches'
更改数组的形状以匹配上面指定的批处理的长度:
weather_batches = reshape(weather_batches, (100,:))
X = weather_batches # переприсвоение
定义目标值数组:
Y = (T[101:1460]) # отсчёт начинается с 101, так как предыдущие 100 наблюдений используются в качестве исходных данных
Y = Y'
转换为神经网络处理可接受的格式:
X = convert(Array{Float32}, X)
Y = convert(Array{Float32}, Y)
创建测试数据集:
将测试样品分成长度为100个观测值的批次:
X_test = df[1461:1820, 3] # определение тестового набора данных
batch_starts_test = 1:1:261 # определение диапазона для цикла
test_batches = [] # определение пустого массива для записи результатов выполнения цикла
for start in batch_starts_test
dop = X_test[start:start+99] # батч на текущем временном шаге
test_batches = vcat(test_batches, dop) # запись батча в массив
end
test_batches = reshape(test_batches, (100,:)) # изменение формы массива для соответствия длине батча, указанной выше:
X_test = convert(Array{Float32}, test_batches) # преобразование в формат приемлимый для обработки нейросетью
构建和训练神经网络:
定义神经网络的体系结构:
model = Flux.Chain(
Dense(100 => 50, elu),
Dense(50 => 25, elu),
Dense(25 => 5, elu),
Dense(5 => 1)
)
定义学习参数:
# Инициализация оптимизатора
learning_rate = 0.001f0
opt = Optimisers.Adam(learning_rate)
state = Optimisers.setup(opt, model) # Создание начального состояния
# Функция потерь
loss(model, x, y) = Flux.mse(model(x), y)
模型训练:
loss_history = []
epochs = 200
for epoch in 1:epochs
# Вычисление градиентов
grads = gradient(model) do m
loss(m, X, Y)
end
# Обновление модели и состояния
state, model = Optimisers.update(state, model, grads[1])
# Расчет и сохранение потерь
current_loss = loss(model, X, Y)
push!(loss_history, current_loss)
# Вывод потерь на каждом шаге
if epoch == 1 || epoch % 10 == 0
println("Epoch $epoch: Loss = $current_loss")
end
end
损失函数变化的可视化:
plot((1:epochs), loss_history, title="Изменение функции потерь", xlabel="Эпоха", ylabel="Функция потерь")
获取预测值:
y_hat_raw = model(X_test) # загрузка тестовой выборки в модель, получение прогноза
y_pred = y_hat_raw'
y_pred = y_pred[:,1]
y_pred = convert(Vector{Float64}, y_pred)
first(y_pred, 5)
预测值的可视化:
days = df[:,1] # формирование массива дней, начиная с первого наблюдения
first(days, 5)
启用后端图形显示方法:
plotlyjs()
从初始数据集生成数据集以进行比较:
df_T = df[:, 3]#df[1471:1820, 3]
first(df_T, 5)
根据初始数据和预测数据绘制温度与时间的相关性:
plot(days, df_T)#plot(days, T[11:end]) #T[11:end]
plot!(days[1560:1820], y_pred)
由于原始数据集具有缺失值已被线性插值替换的部分,因此很难评估训练后的神经网络模型在直线上的性能。
为了做到这一点,真实的数据被上传没有任何差距。:
real_data = DataFrame(CSV.File("$(@__DIR__)/real_data.csv"));
根据真实数据和预测数据绘制温度与时间的关系图:
plot(real_data[1:261,2])
plot!(y_pred)
让我们使用Pearson相关性检查获得值的关系,从而评估获得模型的准确性。:
corr_T = cor(y_pred,real_data[1:261,2])
Pearson相关系数可以取-1到1的值,其中0表示变量之间没有任何关系,-1和1表示密切关系(分别为逆关系和直接关系)。
结论:
在这个例子中,来自过去五年温度观测的数据被预处理,并且神经网络的架构,优化器的参数和损失函数被确定。
该模型经过训练,并显示出预测值与真实数据的相当高但不完美的收敛。 为了提高预测的质量,可以通过改变层的体系结构和增加训练样本来修改神经网络。