繁体   English   中英

为什么我的神经网络无法预测正弦波的下一个值?

[英]Why is my neural network having trouble predicting the next value of a sin wave?

为什么我的神经网络无法预测正弦波的下一个数字?

我不知道我是否需要更好的损失 function 或问题是什么。 它似乎优化了大约 500 步,然后它只是在看起来一点也不像波浪的预测中挣扎。

model 的输入是 120。这是正弦波先前数字的 120。 要求 model 预测下一个数字的位置,我将正弦波值存储在双端队列中。 我将下一个 sin wave 值插入到其双端队列的末尾。

目标和预测是 arrays,形状为 (200,)。
数组中低于 100 的每个索引表示一个负数,高于 100 的每个索引表示一个正数。
所有介于-10之间的百分之一的值都由索引 0 到 100 表示。
在 100 以上,表示01之间的百分之一。 换句话说,200 个可能的数组形式的值来显示神经网络的目标是什么以及预测是什么。

代码(我在 Jupyter Notebook 中分解的代码)...

%matplotlib inline

import torch
import random
import numpy as np
from collections import deque
from matplotlib import pyplot as plt
from matplotlib.pyplot import figure
from torch import nn
import time
import math

plt.rcParams["figure.figsize"]=(12, 8)  

class Network(nn.Module):
    def __init__(self):
        super().__init__()
        
        self.net = nn.Sequential(
            nn.Linear(120, 136),
            nn.ReLU(),
            nn.Dropout(0.05),
            nn.Linear(136, 146),
            nn.ReLU(),
            nn.Dropout(0.05),
            nn.Linear(146, 156),
            nn.ReLU(),
            nn.Dropout(0.05),
            nn.Linear(156, 170),
            nn.ReLU(),
            nn.Linear(170, 188),
            nn.Dropout(0.05),
            nn.ReLU(),
            nn.Linear(188, 200))  

    def forward(self, x):
        return self.net(x)  

online_net = Network().cuda("cuda:2")

optimizer = torch.optim.Adam(online_net.parameters(), lr=1e-5)
device = torch.device("cuda:2" if torch.cuda.is_available() else "cpu")  

sensor_buffer = deque(maxlen=120)
action_buffer = deque(maxlen=120)

[sensor_buffer.append(np.array([random.random() for _ in range(4)]).mean()) for __ in range(121)]
[action_buffer.append(0) for _ in range(121)]  

def format_target(n):
    n = (n * 100)
    l = [-1 for o in range(200)]
    l[int(n)] = 1
    return l  

for steps in range(1400):
    
    adder += (random.random() * 0.2)
    sensor_buffer.append(adder)
    sensor_sinwave = np.sin(sensor_buffer[-1])

    outers = torch.tensor(np.sin(sensor_buffer), dtype=torch.float32).cuda("cuda:2").T

    outer = online_net.forward(outers)

    prediction = torch.argmax(outer).item()

    n_prediction = (prediction * 0.01) -1

    action_buffer.append(n_prediction)

    target = format_target(sensor_sinwave)
    target_t = torch.as_tensor(target, dtype=torch.float32, device=device)

    loss = nn.functional.smooth_l1_loss(outer, target_t)


    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

    if steps % 150 == 0:
        print(loss.item(), n_prediction, sensor_sinwave)

我试图预测的罪恶浪潮在此处输入图像描述

我的预测在此处输入图像描述

您的 model 有两个主要问题:一个是机械问题,一个是理论问题。

  1. 你的损失(和伴随的架构)没有适当地解决 model 问题。 您实际上是在尝试训练回归问题 (R^n -> R),但您将其定义为分类问题 (R^n -> Z^m)。 通常(粗略地),对于分类问题,您将使用交叉熵损失,而对于回归问题,您将使用 L2 损失。 如果您将 model 的 output 维度更改为 1,并将损失更改为 L2,您的状态应该会更好。

  2. 你的 model 对于这样一个简单的 function 来说太复杂了。你的 model 的参数越多,你可能引入的方差就越大。 这相当于更高的过度拟合可能性和更小的泛化机会。 让您的 model 浅几层,您可能会对它的性能感到满意。

这是一个很小的 C++ 代码,用于预测下一个 sin() 值。 希望它对你有用。

#include <cmath>
#include <iostream>
#include <vector>
using namespace std;

const float pi = 4.0f * atanf(1.0f);

int main(void)
{
    // Replace these samples with your input data
    vector<float> samples(120, 0.0f);

    for (size_t i = 0; i < samples.size(); i++)
    {
        const float n = (i + 1) / static_cast<float>(samples.size());
        samples[i] = sin(2 * pi * n);

        cout << samples[i] << endl;
    }

    cout << endl;

    vector<float> arc_samples(120, 0.0f);

    for (size_t i = 0; i < arc_samples.size(); i++)
    {
        arc_samples[i] = asin(samples[i]);

        cout << arc_samples[i] << endl;
    }

    cout << endl;

    size_t avg_count = 0;
    float avg_diff = 0.0f;

    for (size_t i = 1; i < arc_samples.size(); i++)
    {
        avg_diff += fabsf(arc_samples[i] - arc_samples[i - 1]);
        avg_count++;
    }

    avg_diff /= avg_count;

    float next_sample = arc_samples[arc_samples.size() - 1] + avg_diff;

    cout << "Next sin() value = " << sin(next_sample) << endl;

    return 0;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM