신경망에 대한 각도 데이터 인코딩


20

대상 데이터가 각도 벡터 (0 ~ 2 * pi) 인 신경망 (자세한 내용은 중요하지 않음)을 훈련하고 있습니다. 이 데이터를 인코딩하는 방법에 대한 조언을 찾고 있습니다. 현재 내가 시도하고있는 것은 (성공적으로 제한적입니다) :

1) 1-C 인코딩 : 설정 가능한 각도를 1000 정도의 이산 각도로 비운 다음 관련 인덱스에 1을 넣어 특정 각도를 나타냅니다. 이것의 문제는 네트워크가 단순히 0을 모두 출력하는 법을 배우는 것입니다 (거의 정확히 맞기 때문에).

2) 단순 스케일링 : 네트워크 출력 범위 ([0,1])를 [0,2 * pi]로 스케일했습니다. 여기서 문제는 각도가 자연스럽게 원형 토폴로지를 갖는다는 것입니다 (즉, 0.0001과 2 * pi는 실제로 서로 바로 옆에 있습니다). 이 유형의 인코딩을 사용하면 해당 정보가 손실됩니다.

모든 제안을 부탁드립니다!


1
소프트 맥스 출력 레이어를 사용하는 경우 (예 : catagorical (즉, 1-C)) 출력을 사용하는 경우 일반적으로 수행해야하는 네트워크에서 모든 0을 출력하는 데 문제가 없어야합니다.
Lyndon White

7
순전히 추론 적 인 인코딩 아이디어 (나는 그것을 보았거나 테스트하지는 않았지만 보지 못했다)는 각도 ( )를 쌍으로 인코딩하는 것입니다 : . 그렇다면 과 와 같은 모든 값을 가진 연속적인 맵이 될 것이라고 생각합니다 . 나는 이것의 데모를 구축하고 테스트 할 수 있다고 생각합니다. θθ(sin(θ),cos(θ))02π
Lyndon White

나는 이것에 대해 더 생각하고 있었고, 그것이 실제로 당신의 손실 함수에 있다고 생각합니다. 나는 많은 것을 시도하고 싶다. 데모를 만들었지 만 테스트를 완료하지 않았습니다. 내일 언젠가 실험적인 지원으로 자세한 답변을 기대하십시오. (내가 아니라면 날 따라와)
Lyndon White

현재 softmax 레이어를 사용하고 있지 않으며 아마도 문제 일 것입니다. 기회가된다면 오늘 구현하겠습니다! 귀하의 (cos, sin) 아이디어는 매우 흥미 롭습니다. 특히 그 범위를 자동으로 [-1,1]에 넣는 것이 좋습니다 (tanh 활성화 기능으로 작업하는 경우 좋습니다). 나는 당신의 결과를 기대합니다 1
Ari Herman

빠른 업데이트 : softmax 레이어를 구현하려고 시도했지만 여전히 운이 없습니다. 문제는이 문제에 대해 데이터의 "각도"가 어떻게 든 인코딩에서 표현되어야한다는 것입니다. 범주 형 인코딩을 사용하면 대상 데이터의 토폴로지가 손실됩니다. 따라서 0.5 * pi 및 0.05 * pi의 오류는 네트워크와 동일하게 보입니다 (둘 다 잘못된 분류로 간주 됨).
Ari Herman

답변:


18

소개

나는이 질문이 정말로 흥미 롭다는 것을 안다. 누군가가 그것에 종이를 썼다고 가정하지만 그것은 쉬는 날이다. 그래서 나는 참조를 쫓고 싶지 않다.

그래서 우리는 이것을 출력의 표현 / 인코딩으로 간주 할 수 있습니다.이 답변에서 수행합니다. 조금 다른 손실 함수를 사용할 수있는 더 좋은 방법이 있다고 생각합니다. (빼기 모듈로 2 사용하여 아마도 제곱 차이의 합 ).π

그러나 실제 답변으로 계속 진행하십시오.

방법

각도 는 한 쌍의 값, 사인 및 코사인으로 표현할 것을 제안합니다 .θ

인코딩 기능하므로 : 및 디코딩 기능은 : 용 arctan 값은 모든 사분면에서의 방향을 유지하면서 역 탄젠트 인)θ(sin(θ),cos(θ))
(y1,y2)arctan2(y1,y2)

이론적으로 도구 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 축"에 어떤 각도로 출력되는지

임의의 각도로 선 으로이 이미지를 무작위로 생성하는 함수를 구현했습니다 (NB :이 게시물의 이전 버전은 임의의 각도가 아닌 임의의 경사를 사용했습니다. @Ari Herman 덕분에 지적되었습니다. 이제 수정되었습니다). 작업에 대한 성능을 평가하기 위해 여러 신경망을 구성했습니다. 구현에 대한 자세한 내용은 이 Jupyter 노트북에 있습니다. 코드는 모두 Julia 에 있으며 Mocha 신경망 라이브러리를 사용합니다.

비교를 위해, 나는 0.1로 스케일링하는 다른 방법들과 비교하여 그것을 제시한다. 500 통에 넣고 소프트 라벨 softmax를 사용합니다. 나는 마지막에 특히 만족하지 않으며 그것을 조정할 필요가 있다고 느낍니다. 그렇기 때문에 다른 것과 달리 1,000 번 반복하여 1,000 번과 10,000 번으로 실행 된 다른 두 번만 시험해보십시오.

실험 설정

이미지는 픽셀이며 선은 중앙에서 시작하여 가장자리로 이동합니다. 이미지에는 노이즈가없고 흰색 바탕에 "검은 색"선만 있습니다.101×101

각 트레일마다 1,000 개의 훈련과 1,000 개의 테스트 이미지가 무작위로 생성되었습니다.

평가 네트워크는 폭이 500 인 단일 숨겨진 층을 가졌다. 숨겨진 층에는 시그 모이 드 뉴런이 사용되었다.

고정 학습 속도는 0.01이고 고정 운동량은 0.9 인 스토캐스틱 그라디언트 디센트 (Stochastic Gradient Decent)에 의해 훈련되었습니다.

정규화 또는 제거가 사용되지 않았습니다. 어떤 종류의 컨볼 루션도 없었습니다. 간단한 네트워크.이 결과가 일반화 될 것이라고 제안합니다.

테스트 코드 에서 이러한 매개 변수를 조정하는 것은 매우 쉽고 사람들에게 권장합니다. (그리고 테스트에서 버그를 찾으십시오).

결과

내 결과는 다음과 같습니다.

|                        |  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 인코딩보다 성능이 훨씬 뛰어납니다. 1,000 번의 훈련 반복에서 sin / cos가 10,000 번 반복하는 것보다 대부분의 메트릭에서 약 3 배 더 잘 수행되는 정도까지 향상되었습니다.

적어도 부분적으로 10,000 회 반복이 실행되면 훈련 세트에서 상당히 비슷한 평균 제곱 오류가 발생하기 때문에 이것은 부분적으로 일반화 개선과 관련이 있다고 생각합니다.

101×101

또한이 성능을 넘어 서기 위해 절대 규모로 더 나은 신경망이 필요할 것 같습니다. 실험 설정에서 위에서 설명한 매우 간단한 것보다는.

결론.

여기에서 조사한 표현 중 sin / cos 표현이 훨씬 최고인 것 같습니다. 원 주위를 움직일 때 부드러운 값을 갖기 때문에 의미가 있습니다. 나는 또한 arctan2로 역을 수행 할 수 있다는 것을 좋아합니다 .

f(x)=y1y2x


이것은 확실히 스택 교환에서받은 가장 철저한 응답입니다. Julia에 익숙하지 않기 때문에 코드를 검사하기가 어렵습니다. 대신 Python을 사용하여 결과를 복제하려고합니다. 오늘 또는 내일 나중에 결과를 게시하겠습니다.
Ari Herman

비닝이 제대로 수행되지 않았다는 사실에 놀라지 않았지만 (cos, sin) 방법으로 (0,1) 스케일링이 성능을 능가하는 정도에 놀랐습니다. 선의 상승과 실행을 임의로 선택하여 예제를 생성 한 것으로 나타났습니다. 이것은 각도가 균일하게 분포되지 않지만 경사가있는 선을 생성한다고 생각합니다. 이것이 (cos, sin) 방법이 훨씬 더 나은 이유 일 수 있습니까? 대상을 tan (angle) ...으로 설정하면 어떻게됩니까?
Ari Herman

tan(angle)π/4

실제로 다시 구현하려면 julia와 numpy 사이, Mocha와 Caffe 사이에 일대일 맵이 있어야합니다. 읽기 어려운 코드의 특정 부분이 있습니까? Julia는 이해하기 쉬운 언어 여야합니다. 어쩌면 나는 이상한 일을했을 것입니다.
Lyndon White

나는 당신의 코드를 읽었고 모든 것이 정확 해 보입니다. 아직도, 나는 내 자신의 버전을 작성하고 싶었습니다. 그렇게하는 것이 일반적으로 유익하기 때문입니다. 내 구현은 귀하의 구현과 약간 다르므로 결과를 비교하는 것이 흥미로울 것입니다. 다음 몇 시간 내에 게시하겠습니다.
Ari Herman

5

Lyndon White 의 제안 된 인코딩을 비닝 접근법 과 비교하는 또 다른 Python 구현이 있습니다. 아래 코드는 다음과 같은 출력을 생성했습니다.

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

(sin(θ),cos(θ))(sin(θ),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

여기 내 실험의 파이썬 버전이 있습니다. 구현의 많은 세부 사항을 동일하게 유지했습니다. 특히 동일한 이미지 크기, 네트워크 계층 크기, 학습 속도, 운동량 및 성공 지표를 사용합니다.

테스트 된 각 네트워크에는 로지스틱 뉴런이있는 하나의 숨겨진 계층 (크기 = 500)이 있습니다. 출력 뉴런은 명시된 바와 같이 선형 또는 소프트 맥스이다. 나는 독립적으로 무작위로 생성 된 1,000 개의 훈련 이미지와 1,000 개의 테스트 이미지를 사용했습니다 (따라서 반복이있을 수 있음). 훈련은 훈련 세트를 통해 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 %

1-500 인코딩의 테스트 오류 :

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)

시원하고 키가 다릅니다. 각 이미지에 대해 한 번만 훈련합니다. 각 이미지를 1,000 번 또는 10,000 번 훈련하고 있습니다. 특히 상대적으로 적은 양의 데이터에 대한 훈련을 할 때 훈련 데이터가 정상이지만 여러 번 반복합니다 (그리고 이것을 배우기 위해 출판 할 수없는 한 학부 논문 만 가져 왔지만 다른 이야기입니다). 그 말로, 테이블에 1 개의 iter 열을 추가해야합니다. 유익 할 것입니다
Lyndon White

비슷한 목표를 가진 유사하지만 동일하지 않은 이미지에 대한 교육은 해당 네트워크에 유사하게 영향을 줄 것이라고 생각합니다. 그것이 사실이라면, 훈련되는 임의의 이미지의 수를 늘리는 것보다는 작은 훈련 세트를 통해 여러 번 반복하는 것이 좋습니다. 이것이 사실이 아니라고 말하는가?
Ari Herman

비슷하지만이 예제 작업의 경우 가능한 모든 이미지를 표시하여 테스트가 기차와 겹치므로 일반 시험이 작동하지 않는 문제가 없습니다. 100,000 개 훈련 이미지 (1000 * 1000 개 훈련 이미지 * 반복)를 수행하는 것이 더 중요합니다.
Lyndon White

당신은 맞습니다, 나는 그 문제를 해결할 것입니다. 내 코드에는 훨씬 중요한 문제가 있습니다. (cos, sin) 표현에 필요한 음수 값을 생성 할 수없는 물류 뉴런을 사용하고 있습니다. 도! 가능한 빨리 코드를 수정하고 다시 게시하겠습니다.
Ari Herman

(아직 그렇게하지 않은 경우) 신경 실수 네트워크를 처음부터 구현할 때 가치가있는 Graident Check 를 수행하는 데 관심 이있을 수 있습니다. 사소한 실수를하고 네트워크가 여전히 대부분 작동하기가 매우 쉽기 때문입니다. Re : Neuron : 네, 시그 모이 드 히든 레이어 위에 선형 출력 레이어가 있습니다
Lyndon White

1

각도를 인코딩하는 또 다른 방법은 두 가지 값의 집합입니다.

y1 = 최대 (0, θ)

y2 = 최대 (0, θ)

theta_out = y1-y2

그래디언트가 theta = 0에서 정의되지 않았다는 점에서 arctan2와 비슷한 문제가 있습니다. 네트워크를 훈련시키고 다른 인코딩과 비교할 시간 없지만 백서에서는 기술이 합리적으로 성공한 것으로 보입니다.


1
이것은 한 게시물에서 다른 질문과 혼합 된 답변처럼 보입니다. 이 사이트는 포럼과는 조금 다르게 운영됩니다. 여기에 답은 원래 질문에 대답하는 데 집중해야합니다. 그리고 다른 질문이나 의견이 있으면 게시하십시오.
Karolis Koncevičius
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.