神经网络的编码角度数据


20

我正在训练一个神经网络(细节并不重要),其中目标数据是角度矢量(0到2 * pi之间)。我正在寻找有关如何编码此数据的建议。这是我目前正在尝试的方法(成功有限):

1)C的1编码:我将设置的可能角度分成1000个左右的离散角度,然后通过在相关索引处加1来指示特定角度。这样做的问题在于,网络只是学习输出全0(因为这几乎是完全正确的)。

2)简单缩放:我将网络输出范围([0,1])缩放为[0,2 * pi]。这里的问题是角度自然具有圆形拓扑(即,0.0001和2 * pi实际上彼此紧邻)。使用这种类型的编码,该信息会丢失。

任何建议,将不胜感激!


1
如果使用softmax输出层,则网络输出全零应该不会有问题-如果使用分类(即C的1-)输出,通常应该这样做。
林顿·怀特

7
一个纯粹的投机编码的想法(我从来没见过它做或测试,但我没有看过)是编码的角度()为一对:θ θ COS θ 。我认为,那将是一个连续的地图就像所有的值02 π彼此接近。我想我可能会对此进行演示并进行测试。θθ(sin(θ),cos(θ))02π
林顿·怀特

我一直在考虑这个问题,我想实际上可能全部都在损失函数中。我想尝试一堆东西。我进行了演示,但是还没有完成测试。期待明天某个时候有实验性支持的详细答案。(如果我不给我打电话)
林登·怀特

我当前未使用softmax层,这可能是问题所在。如果有机会,我将在今天实施!您的(cos,sin)想法非常有趣,我特别喜欢它会自动将该范围放入[-1,1](如果您正在使用tanh激活功能,则很好)。我期待看到您的结果1
Ari Herman

快速更新:我尝试实现softmax层,但仍然没有运气。我认为问题在于,对于此问题,至关重要的是,以某种方式在编码中表示数据的“角度”。使用分类编码,将丢失目标数据的拓扑。因此,网络的误差为0.5 * pi和0.05 * pi(将其视为错误的分类)。
阿里·赫尔曼

Answers:


18

介绍

我觉得这个问题真的很有趣,我假设有人在上面写了一篇论文,但这是我的假期,所以我不想去追寻参考文献。

因此,我们可以将其视为输出的表示形式/编码,我在此答案中对此进行了说明。我仍然认为有更好的方法,您可以使用稍微不同的损失函数。(也许求和的平方差,使用减法模2 )。π

但从实际答案开始。

方法

我建议将角度表示为一对值,即其正弦和余弦。θ

因此,编码功能为: 和解码功能是:θθcosθ
对于arctan2为反正切,在所有象限中都保持方向)ÿ1个ÿ2Arctan2ÿ1个ÿ2

从理论上讲,如果您的工具atan2用作图层功能,则可以等效地直接使用这些角度(精确地输入2个输入并产生1个输出)。 TensorFlow现在执行此操作,并在其上支持梯度下降,但并非旨在用于此用途。我调查了使用out = atan2(sigmoid(ylogit), sigmoid(xlogit)) 损失函数min((pred - out)^2, (pred - out - 2pi)^2)。我发现它的训练远比使用outs = tanh(ylogit), outc = tanh(xlogit)) 具有损失功能的训练差0.5((sin(pred) - outs)^2 + (cos(pred) - outc)^2。我认为这可以归因于梯度不连续atan2

我在这里的测试将其作为预处理功能运行

为了对此进行评估,我定义了一个任务:

给定黑白图像,表示空白背景上的单行输出该行与“正x轴”所成的角度

我实现了一个函数,用随机角度的线条随机生成这些图像(注意:本文的早期版本使用随机斜率,而不是随机角度。感谢@Ari Herman指出了这一点,现在已修复)。我构建了多个神经网络来评估该任务的性能。完整的实现细节在Jupyter笔记本中。代码全部在Julia中,并且我使用了Mocha神经网络库。

为了进行比较,我将其与缩放到0,1的替代方法进行比较。并放入500箱中,并使用软标签softmax。我对最后一个并不特别满意,觉得需要调整一下。这就是为什么与其他程序不同,我仅对它进行了1,000次迭代测试,而对其他两个程序分别进行了1,000次和10,000次测试

实验装置

图像尺寸像素,线条在中央并向边缘延伸。在白色背景上,图像中没有噪点等,只是“黑”线。101×101

对于每个跟踪,随机生成了1,000个训练和1,000个测试图像。

评估网络只有一个宽度为500的隐藏层。在该隐藏层中使用了S型神经元。

它由随机梯度体面训练,固定学习率为0.01,固定动量为0.9。

没有使用正则化或辍学。也没有任何形式的卷积等。一个简单的网络,我希望可以将这些结果推广

测试代码中调整这些参数非常容易,我鼓励人们这样做。(并在测试中查找错误)。

结果

我的结果如下:

|                        |  500 bins    |  scaled to 0-1 |  Sin/Cos     |  scaled to 0-1 |  Sin/Cos     |
|                        | 1,000 Iter   | 1,000 Iter     | 1,000 iter   | 10,000 Iter    | 10,000 iter  |
|------------------------|--------------|----------------|--------------|----------------|--------------|
| mean_error             | 0.4711263342 | 0.2225284486   | 2.099914718  | 0.1085846429   | 2.1036656318 |
| std(errors)            | 1.1881991421 | 0.4878383767   | 1.485967909  | 0.2807570442   | 1.4891605068 |
| minimum(errors)        | 1.83E-006    | 1.82E-005      | 9.66E-007    | 1.92E-006      | 5.82E-006    |
| median(errors)         | 0.0512168533 | 0.1291033982   | 1.8440767072 | 0.0562908143   | 1.8491085947 |
| maximum(errors)        | 6.0749693965 | 4.9283551248   | 6.2593307366 | 3.735884823    | 6.2704853962 |
| accurancy              | 0.00%        | 0.00%          | 0.00%        | 0.00%          | 0.00%        |
| accurancy_to_point001  | 2.10%        | 0.30%          | 3.70%        | 0.80%          | 12.80%       |
| accurancy_to_point01   | 21.90%       | 4.20%          | 37.10%       | 8.20%          | 74.60%       |
| accurancy_to_point1    | 59.60%       | 35.90%         | 98.90%       | 72.50%         | 99.90%       |

我所说的误差是神经网络输出的角度与真实角度之差的绝对值。因此,平均误差(例如)是平均值这种差异等1000的测试案例,我不知道,我不应该通过使发言权的错误来重新调整其等于π的误差7π4π4)。

我还介绍了各种粒度级别的准确性。准确性是测试用例的一部分,因此它被纠正了。因此accuracy_to_point01,如果输出在真实角度的0.01以内,则认为它是正确的。这些表示形式都没有得到完美的结果,但是鉴于浮点数学的工作原理,这一点也不奇怪。

如果您看一下这篇文章的历史,您会发现结果确实对他们有些干扰,每次我重新运行它时都会略有不同。但是,总的价值顺序和规模保持不变。因此,我们可以得出一些结论。

讨论区

到目前为止,使用softmax进行分箱的效果最差,因为我不确定我在实现过程中没有搞砸。虽然它确实比猜测率略高。如果只是猜测,我们将得到的平均误差π

sin / cos编码的性能明显优于缩放的0-1编码。改进的程度是,在1000次训练迭代中,sin / cos在大多数指标上的性能比在10,000次迭代中进行缩放的性能好大约3倍。

我认为,这部分与提高通用性有关,因为至少在进行10,000次迭代后,两者在训练集上的均方误差都变得非常相似。

鉴于角度可能或多或少是任何实数,因此在此任务上可能会有最佳性能的上限,但是并非所有此类天使都以的分辨率产生不同的线条101×101像素。因此,例如,由于角度45.0和45.0000001都以该分辨率绑定到同一张图像,因此没有任何方法能够完美地解决这两个问题。

在绝对规模上超越此性能似乎也需要一个更好的神经网络。而不是上面实验设置中概述的非常简单的方法。

结论。

在我这里调查的表示中,似乎sin / cos表示是最好的。这确实是有道理的,因为它在您绕圆移动时确实具有平滑的值。我也喜欢用arctan2进行逆运算,这很优雅。

我认为所提出的任务足以为网络提出合理的挑战。虽然我猜确实是在学习对进行曲线拟合FX=ÿ1个ÿ2X


这无疑是我在交换堆栈时收到的最彻底的响应。由于我不熟悉Julia,所以我很难检查您的代码...因此,我将尝试使用Python复制您的结果。我将在今天晚些时候或明天发布调查结果。
阿里·赫尔曼

虽然我并不对合并效果不好感到惊讶,但我对(cos,sin)方法在(0,1)缩放方面的表现感到惊讶。我注意到您是通过随机选择行的上升和运行来生成示例的。我认为,这将生成其角度不是均匀分布但斜率是直线的线。这可能就是为什么(cos,sin)方法执行得好得多的原因吗?如果将目标设为tan(angle)...,会发生什么?
阿里·赫尔曼

tan(angle)π/4

如果您真的想重新实现它,那么在julia和numpy之间以及在Mocha和Caffe之间应该有接近一对一的映射。您是否难于阅读代码中的特定部分?朱莉娅应该是一种易于理解的语言。所以也许我做了一些奇怪的事情。
林登·怀特

我确实读完了您的代码,一切似乎都正确了。不过,我还是想编写自己的版本,因为这样做通常很有启发性。我的实现与您的实现略有不同,因此比较结果会很有趣。我将在接下来的几个小时内发布它们。
阿里·赫尔曼

5

这是另一个Python实现,将Lyndon White提出的编码与分类方法进行了比较。下面的代码产生以下输出:

Training Size: 100
Training Epochs: 100
Encoding: cos_sin
Test Error: 0.017772154610047136
Encoding: binned
Test Error: 0.043398792553251526

Training Size: 100
Training Epochs: 500
Encoding: cos_sin
Test Error: 0.015376604917819397
Encoding: binned
Test Error: 0.032942592915322394

Training Size: 1000
Training Epochs: 100
Encoding: cos_sin
Test Error: 0.007544091937411164
Encoding: binned
Test Error: 0.012796594492198667

Training Size: 1000
Training Epochs: 500
Encoding: cos_sin
Test Error: 0.0038051515079569097
Encoding: binned
Test Error: 0.006180633805557207

如您所见,虽然分箱方法在此玩具任务中表现出色,但 θcosθ编码在所有训练配置中的表现都更好,有时幅度相当大。我怀疑作为特定的任务变得更加复杂,使用的好处林登·怀特θcosθ 代表性将变得更加明显。

import matplotlib.pyplot as plt
import numpy as np
import torch
import torch.nn as nn
import torch.utils.data

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")


class Net(nn.Module):
    def __init__(self, input_size, hidden_size, num_out):
        super(Net, self).__init__()
        self.fc1 = nn.Linear(input_size, hidden_size)
        self.sigmoid = nn.Sigmoid()
        self.fc2 = nn.Linear(hidden_size, num_out)

    def forward(self, x):
        out = self.fc1(x)
        out = self.sigmoid(out)
        out = self.fc2(out)
        return out


def gen_train_image(angle, side, thickness):
    image = np.zeros((side, side))
    (x_0, y_0) = (side / 2, side / 2)
    (c, s) = (np.cos(angle), np.sin(angle))
    for y in range(side):
        for x in range(side):
            if (abs((x - x_0) * c + (y - y_0) * s) < thickness / 2) and (
                    -(x - x_0) * s + (y - y_0) * c > 0):
                image[x, y] = 1

    return image.flatten()


def gen_data(num_samples, side, num_bins, thickness):
    angles = 2 * np.pi * np.random.uniform(size=num_samples)
    X = [gen_train_image(angle, side, thickness) for angle in angles]
    X = np.stack(X)

    y = {"cos_sin": [], "binned": []}
    bin_size = 2 * np.pi / num_bins
    for angle in angles:
        idx = int(angle / bin_size)
        y["binned"].append(idx)
        y["cos_sin"].append(np.array([np.cos(angle), np.sin(angle)]))

    for enc in y:
        y[enc] = np.stack(y[enc])

    return (X, y, angles)


def get_model_stuff(train_y, input_size, hidden_size, output_sizes,
                    learning_rate, momentum):
    nets = {}
    optimizers = {}

    for enc in train_y:
        net = Net(input_size, hidden_size, output_sizes[enc])
        nets[enc] = net.to(device)
        optimizers[enc] = torch.optim.SGD(net.parameters(), lr=learning_rate,
                                          momentum=momentum)

    criterions = {"binned": nn.CrossEntropyLoss(), "cos_sin": nn.MSELoss()}
    return (nets, optimizers, criterions)


def get_train_loaders(train_X, train_y, batch_size):
    train_X_tensor = torch.Tensor(train_X)

    train_loaders = {}

    for enc in train_y:
        if enc == "binned":
            train_y_tensor = torch.tensor(train_y[enc], dtype=torch.long)
        else:
            train_y_tensor = torch.tensor(train_y[enc], dtype=torch.float)

        dataset = torch.utils.data.TensorDataset(train_X_tensor, train_y_tensor)
        train_loader = torch.utils.data.DataLoader(dataset=dataset,
                                                   batch_size=batch_size,
                                                   shuffle=True)
        train_loaders[enc] = train_loader

    return train_loaders


def show_image(image, side):
    img = plt.imshow(np.reshape(image, (side, side)), interpolation="nearest",
                     cmap="Greys")
    plt.show()


def main():
    side = 101
    input_size = side ** 2
    thickness = 5.0
    hidden_size = 500
    learning_rate = 0.01
    momentum = 0.9
    num_bins = 500
    bin_size = 2 * np.pi / num_bins
    half_bin_size = bin_size / 2
    batch_size = 50
    output_sizes = {"binned": num_bins, "cos_sin": 2}
    num_test = 1000

    (test_X, test_y, test_angles) = gen_data(num_test, side, num_bins,
                                             thickness)

    for num_train in [100, 1000]:

        (train_X, train_y, train_angles) = gen_data(num_train, side, num_bins,
                                                    thickness)
        train_loaders = get_train_loaders(train_X, train_y, batch_size)

        for epochs in [100, 500]:

            (nets, optimizers, criterions) = get_model_stuff(train_y, input_size,
                                                             hidden_size, output_sizes,
                                                             learning_rate, momentum)

            for enc in train_y:
                optimizer = optimizers[enc]
                net = nets[enc]
                criterion = criterions[enc]

                for epoch in range(epochs):
                    for (i, (images, ys)) in enumerate(train_loaders[enc]):
                        optimizer.zero_grad()

                        outputs = net(images.to(device))
                        loss = criterion(outputs, ys.to(device))
                        loss.backward()
                        optimizer.step()


            print("Training Size: {0}".format(num_train))
            print("Training Epochs: {0}".format(epochs))
            for enc in train_y:
                net = nets[enc]
                preds = net(torch.tensor(test_X, dtype=torch.float).to(device))
                if enc == "binned":
                    pred_bins = np.array(preds.argmax(dim=1).detach().cpu().numpy(),
                                         dtype=np.float)
                    pred_angles = bin_size * pred_bins + half_bin_size
                else:
                    pred_angles = torch.atan2(preds[:, 1], preds[:, 0]).detach().cpu().numpy()
                    pred_angles[pred_angles < 0] = pred_angles[pred_angles < 0] + 2 * np.pi

                print("Encoding: {0}".format(enc))
                print("Test Error: {0}".format(np.abs(pred_angles - test_angles).mean()))

            print()


if __name__ == "__main__":
    main()

3

这是我的实验的Python版本。我将实现的许多细节保持不变,尤其是我使用了相同的图像大小,网络层大小,学习率,动力和成功指标。

每个测试的网络都有一个带有逻辑神经元的隐藏层(大小= 500)。如上所述,输出神经元为线性或softmax。我使用了1000张训练图像和1000张测试图像,它们是独立,随机生成的(因此可能会重复)。训练包括整个训练集的50次迭代。

使用合并和“高斯”编码(我所起的名字;类似于合并,但目标输出向量的格式为exp(-pi *([1,2,3,... ,500]-idx)** 2),其中idx是与正确角度相对应的索引)。代码如下;这是我的结果:

(cos,sin)编码的测试错误:

1,000个训练图像,1,000个测试图像,50次迭代,线性输出

  • 均值:0.0911558142071

  • 中位数:0.0429723541743

  • 最少:2.77769843793e-06

  • 最多:6.2608513539

  • 精度到0.1:85.2%

  • 精确到0.01:11.6%

  • 精度到0.001:1.0%

[-1,1]编码的测试错误:

1,000个训练图像,1,000个测试图像,50次迭代,线性输出

  • 均值:0.234181700523

  • 中位数:0.17460197307

  • 最少:0.000473665840258

  • 最多:6.00637777237

  • 精度到0.1:29.9%

  • 精度到0.01:3.3%

  • 精度到0.001:0.1%

500个编码中的1个的测试错误:

1,000张训练图像,1,000张测试图像,50次迭代,softmax输出

  • 均值:0.0298767021922

  • 中位数:0.00388858079174

  • 最低:4.08712407829e-06

  • 最大值:6.2784479965

  • 精度至0.1:99.6%

  • 精确到0.01:88.9%

  • 精度到0.001:13.5%

高斯编码的测试错误:

1,000张训练图像,1,000张测试图像,50次迭代,softmax输出

  • 均值:0.0296905377463
  • 中位数:0.00365867335107
  • 最低:4.08712407829e-06
  • 最大值:6.2784479965
  • 精度至0.1:99.6%
  • 精度到0.01:90.8%
  • 精度到0.001:14.3%

我无法弄清楚为什么我们的结果似乎相互矛盾,但似乎值得进一步研究。

# -*- coding: utf-8 -*-
"""
Created on Mon Jun 13 16:59:53 2016

@author: Ari
"""

from numpy import savetxt, loadtxt, round, zeros, sin, cos, arctan2, clip, pi, tanh, exp, arange, dot, outer, array, shape, zeros_like, reshape, mean, median, max, min
from numpy.random import rand, shuffle
import matplotlib.pyplot as plt

###########
# Functions
###########

# Returns a B&W image of a line represented as a binary vector of length width*height
def gen_train_image(angle, width, height, thickness):
    image = zeros((height,width))
    x_0,y_0 = width/2, height/2
    c,s = cos(angle),sin(angle)
    for y in range(height):
        for x in range(width):
            if abs((x-x_0)*c + (y-y_0)*s) < thickness/2 and -(x-x_0)*s + (y-y_0)*c > 0:
                image[x,y] = 1
    return image.flatten()

# Display training image    
def display_image(image,height, width):    
    img = plt.imshow(reshape(image,(height,width)), interpolation = 'nearest', cmap = "Greys")
    plt.show()    

# Activation function
def sigmoid(X):
    return 1.0/(1+exp(-clip(X,-50,100)))

# Returns encoded angle using specified method ("binned","scaled","cossin","gaussian")
def encode_angle(angle, method):
    if method == "binned": # 1-of-500 encoding
        X = zeros(500)
        X[int(round(250*(angle/pi + 1)))%500] = 1
    elif method == "gaussian": # Leaky binned encoding
        X = array([i for i in range(500)])
        idx = 250*(angle/pi + 1)
        X = exp(-pi*(X-idx)**2)
    elif method == "scaled": # Scaled to [-1,1] encoding
        X = array([angle/pi])
    elif method == "cossin": # Oxinabox's (cos,sin) encoding
        X = array([cos(angle),sin(angle)])
    else:
        pass
    return X

# Returns decoded angle using specified method
def decode_angle(X, method):
    if method == "binned" or method == "gaussian": # 1-of-500 or gaussian encoding
        M = max(X)
        for i in range(len(X)):
            if abs(X[i]-M) < 1e-5:
                angle = pi*i/250 - pi
                break
#        angle = pi*dot(array([i for i in range(500)]),X)/500  # Averaging
    elif method == "scaled": # Scaled to [-1,1] encoding
        angle = pi*X[0]
    elif method == "cossin": # Oxinabox's (cos,sin) encoding
        angle = arctan2(X[1],X[0])
    else:
        pass
    return angle

# Train and test neural network with specified angle encoding method
def test_encoding_method(train_images,train_angles,test_images, test_angles, method, num_iters, alpha = 0.01, alpha_bias = 0.0001, momentum = 0.9, hid_layer_size = 500):
    num_train,in_layer_size = shape(train_images)
    num_test = len(test_angles)

    if method == "binned":
        out_layer_size = 500
    elif method == "gaussian":
        out_layer_size = 500
    elif method == "scaled":
        out_layer_size = 1
    elif method == "cossin":
        out_layer_size = 2
    else:
        pass

    # Initial weights and biases
    IN_HID = rand(in_layer_size,hid_layer_size) - 0.5 # IN --> HID weights
    HID_OUT = rand(hid_layer_size,out_layer_size) - 0.5 # HID --> OUT weights
    BIAS1 = rand(hid_layer_size) - 0.5 # Bias for hidden layer
    BIAS2 = rand(out_layer_size) - 0.5 # Bias for output layer

    # Initial weight and bias updates
    IN_HID_del = zeros_like(IN_HID)
    HID_OUT_del = zeros_like(HID_OUT)
    BIAS1_del = zeros_like(BIAS1)
    BIAS2_del = zeros_like(BIAS2)

    # Train
    for j in range(num_iters):
        for i in range(num_train):
            # Get training example
            IN = train_images[i]
            TARGET = encode_angle(train_angles[i],method) 

            # Feed forward and compute error derivatives
            HID = sigmoid(dot(IN,IN_HID)+BIAS1)

            if method == "binned" or method == "gaussian": # Use softmax
                OUT = exp(clip(dot(HID,HID_OUT)+BIAS2,-100,100))
                OUT = OUT/sum(OUT)
                dACT2 = OUT - TARGET
            elif method == "cossin" or method == "scaled": # Linear
                OUT = dot(HID,HID_OUT)+BIAS2 
                dACT2 = OUT-TARGET 
            else:
                print("Invalid encoding method")

            dHID_OUT = outer(HID,dACT2)
            dACT1 = dot(dACT2,HID_OUT.T)*HID*(1-HID)
            dIN_HID = outer(IN,dACT1)
            dBIAS1 = dACT1
            dBIAS2 = dACT2

            # Update the weight updates 
            IN_HID_del = momentum*IN_HID_del + (1-momentum)*dIN_HID
            HID_OUT_del = momentum*HID_OUT_del + (1-momentum)*dHID_OUT
            BIAS1_del = momentum*BIAS1_del + (1-momentum)*dBIAS1
            BIAS2_del = momentum*BIAS2_del + (1-momentum)*dBIAS2

            # Update the weights
            HID_OUT -= alpha*dHID_OUT
            IN_HID -= alpha*dIN_HID
            BIAS1 -= alpha_bias*dBIAS1
            BIAS2 -= alpha_bias*dBIAS2

    # Test
    test_errors = zeros(num_test)
    angles = zeros(num_test)
    target_angles = zeros(num_test)
    accuracy_to_point001 = 0
    accuracy_to_point01 = 0
    accuracy_to_point1 = 0

    for i in range(num_test):

        # Get training example
        IN = test_images[i]
        target_angle = test_angles[i]

        # Feed forward
        HID = sigmoid(dot(IN,IN_HID)+BIAS1)

        if method == "binned" or method == "gaussian":
            OUT = exp(clip(dot(HID,HID_OUT)+BIAS2,-100,100))
            OUT = OUT/sum(OUT)
        elif method == "cossin" or method == "scaled":
            OUT = dot(HID,HID_OUT)+BIAS2 

        # Decode output 
        angle = decode_angle(OUT,method)

        # Compute errors
        error = abs(angle-target_angle)
        test_errors[i] = error
        angles[i] = angle

        target_angles[i] = target_angle
        if error < 0.1:
            accuracy_to_point1 += 1
        if error < 0.01: 
            accuracy_to_point01 += 1
        if error < 0.001:
            accuracy_to_point001 += 1

    # Compute and return results
    accuracy_to_point1 = 100.0*accuracy_to_point1/num_test
    accuracy_to_point01 = 100.0*accuracy_to_point01/num_test
    accuracy_to_point001 = 100.0*accuracy_to_point001/num_test

    return mean(test_errors),median(test_errors),min(test_errors),max(test_errors),accuracy_to_point1,accuracy_to_point01,accuracy_to_point001

# Dispaly results
def display_results(results,method):
    MEAN,MEDIAN,MIN,MAX,ACC1,ACC01,ACC001 = results
    if method == "binned":
        print("Test error for 1-of-500 encoding:")
    elif method == "gaussian":
        print("Test error for gaussian encoding: ")
    elif method == "scaled":
        print("Test error for [-1,1] encoding:")
    elif method == "cossin":
        print("Test error for (cos,sin) encoding:")
    else:
        pass
    print("-----------")
    print("Mean: "+str(MEAN))
    print("Median: "+str(MEDIAN))
    print("Minimum: "+str(MIN))
    print("Maximum: "+str(MAX))
    print("Accuracy to 0.1: "+str(ACC1)+"%")
    print("Accuracy to 0.01: "+str(ACC01)+"%")
    print("Accuracy to 0.001: "+str(ACC001)+"%")
    print("\n\n")


##################
# Image parameters
##################
width = 100 # Image width
height = 100 # Image heigth
thickness = 5.0 # Line thickness

#################################
# Generate training and test data
#################################
num_train = 1000
num_test = 1000
test_images = []
test_angles = []
train_images = []
train_angles = []
for i in range(num_train):
    angle = pi*(2*rand() - 1)
    train_angles.append(angle)
    image = gen_train_image(angle,width,height,thickness)
    train_images.append(image)
for i in range(num_test):
    angle = pi*(2*rand() - 1)
    test_angles.append(angle)
    image = gen_train_image(angle,width,height,thickness)
    test_images.append(image)
train_angles,train_images,test_angles,test_images = array(train_angles),array(train_images),array(test_angles),array(test_images)



###########################
# Evaluate encoding schemes
###########################
num_iters = 50

# Train with cos,sin encoding
method = "cossin"
results1 = test_encoding_method(train_images, train_angles, test_images, test_angles, method, num_iters)
display_results(results1,method)

# Train with scaled encoding
method = "scaled"
results3 = test_encoding_method(train_images, train_angles, test_images, test_angles, method, num_iters)
display_results(results3,method)

# Train with binned encoding
method = "binned"
results2 = test_encoding_method(train_images, train_angles, test_images, test_angles, method, num_iters)
display_results(results2,method)

# Train with gaussian encoding
method = "gaussian"
results4 = test_encoding_method(train_images, train_angles, test_images, test_angles, method, num_iters)
display_results(results4,method)

酷,在关键上有所不同。您仅对每个图像进行一次训练。我正在对每个图像进行1000次或10,000次的训练。尽管训练数据是多次迭代是正常的,尤其是在以相对少量的数据进行训练时(并且我只用一个无法发表的本科论文来学习该知识,但这是另一回事了)。话虽如此,我应该在表中添加1个iter列。那将是
Lyndon White

我认为对具有相似目标的相似(但不完全相同)图像进行训练会类似地影响该网络。如果是这样,那么简单地增加要对其进行训练的随机图像的数量,而不是通过较小的训练集进行多次迭代就可以了。您是说不是这样吗?
Ari Herman

这是相似的,但是对于本示例任务而言,它没有问题,最终您将显示所有可能的图像,因此您的测试将与您的训练重叠,因此测试通用性将无法正常工作。更重要的是,尽管您执行了100,000个训练图像,即<1000 * 1000个训练图像*迭代。
Lyndon White

您是正确的,我将解决该问题。我的代码还有一个更大的问题:我使用的逻辑神经元无法产生(cos,sin)表示所需的负值。天哪!我将修改我的代码并尽快重新发布。
Ari Herman

您可能(如果尚未这样做)对进行Graident Check感兴趣,这对于从头开始实施神经网络非常有价值,因为很容易犯一个小错误,并使您的网络仍然可以正常工作。回复:神经元:是的,我有一个线性输出层,位于S形隐藏层上
Lyndon White

1

编码角度的另一种方法是设置两个值:

y1 =最大值(0,θ)

y2 = max(0,-theta)

theta_out = y1-y2

这将有类似的问题,以arctan2,该梯度在THETA = 0不确定我没有训练网络,并比较了其他编码,但在当时纸技术似乎相当成功。


1
在一个帖子中,这似乎是一个答案与另一个问题的混合体。该网站的运作方式与论坛的运作方式有所不同。这里的答案应该集中在回答原始问题上。如果您还有其他问题或评论,则应这样发布。
KarolisKoncevičius
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.