Sinir Ağı için Kodlama Açısı Verileri


20

Hedef verilerin bir açı vektörü (0 ile 2 * pi arasında) olduğu bir sinir ağını (ayrıntılar önemli değil) eğitiyorum. Bu verilerin nasıl kodlanacağı konusunda tavsiye arıyorum. İşte şu anda çalışıyorum (sınırlı bir başarı ile):

1) C-1 kodlaması: Kurulum olası açılarını 1000 veya daha fazla farklı açılara oturttum ve sonra ilgili indekse 1 koyarak belirli bir açıyı gösteririm. Buradaki sorun, ağın tüm 0'ları vermeyi öğrenmesidir (çünkü bu neredeyse tam olarak doğrudur).

2) Basit ölçeklendirme: Ağların çıkış aralığını ([0,1]) [0,2 * pi] olarak ölçeklendirdim. Buradaki problem, açıların doğal olarak dairesel bir topolojiye sahip olmasıdır (yani 0.0001 ve 2 * pi aslında birbirlerinin hemen yanındadır). Bu tür kodlama ile bu bilgiler kaybolur.

Herhangi bir öneri mutluluk duyacağız!


1
Eğer bir softmax çıkış katmanı kullanıyorsanız, genellikle bir katagorik (yani 1-C-C) çıkışı kullanıyorsanız, tüm sıfırları veren ağ ile ilgili bir problem yaşamamalısınız.
Lyndon White

7
Tamamen spekülatif bir kodlama fikri (yapıldığını veya test etmediğini gördüm, ancak bakmadım), açınızı ( ) bir çift olarak : . O zaman ve gibi tüm değerlerin birbirine yakın olduğu sürekli bir harita olacağını düşünüyorum . Sanırım bunun bir demosunu yapıp test edebilirim. θ dönüs ümü altında, ( sin ( θ ) , cos ( θ ) ) 0 2 πθθ(günah(θ),marul(θ))02π
Lyndon White

Ben bu konuda biraz daha düşünüyorum, ve aslında tüm kayıp fonksiyonunuzda olabilir düşünüyorum. Bir sürü şey denemek istiyorum. Demoyu yaptım, ancak testleri bitirmedim. Yarın deneysel destekle ayrıntılı bir cevap bekliyoruz. (Yapmazsam beni dürt)
Lyndon White

Şu anda bir softmax katman kullanmıyorum ve muhtemelen sorun bu. Eğer bir şansım olursa bugün uygulayacağım! (Cos, sin) fikriniz çok ilginç ve özellikle bu aralığı otomatik olarak [-1,1] 'e koymasını seviyorum (tanh aktivasyon işleviyle çalışıyorsanız iyi). Sonuçlarınızı görmek için sabırsızlanıyorum1
Ari Herman

Hızlı bir güncelleme: Bir softmax katmanı uygulamayı denedim ve hala şansım yok. Sorun, bence, bu sorun için kodlamada verilerin "açısallığı" bir şekilde temsil edilmesi önemlidir. Kategorik bir kodlama ile hedef verilerin topolojisi kaybolur. Bu nedenle 0,5 * pi ve 0,05 * pi'lik bir hata ağ ile aynı görünür (her ikisini de yanlış kategoriler olarak görür).
Ari Herman

Yanıtlar:


18

Giriş

Bu soruyu gerçekten ilginç buluyorum, birisinin üzerine bir kağıt yayınladığını varsayıyorum, ama bu benim günüm, bu yüzden referansları takip etmek istemiyorum.

Bu yüzden, bu cevapta yaptığım çıkışın bir temsili / kodlaması olarak düşünebiliriz. Biraz daha farklı bir kayıp fonksiyonu kullanabileceğiniz daha iyi bir yol olduğunu düşünmeye devam ediyorum. (Belki çıkarma modülo 2 kullanarak kare farklılıkların toplamı ).π

Ama asıl cevaptan sonra.

Yöntem

Bir açı teklif bir değer çifti, onun sinüs ve kosinüs gibi temsil edilebilir.θ

Kodlama işlevi şöyledir: ve kod çözme işlevi: için arctan2 tüm kadranlarında yönünü koruyarak, ters teğet olmak üzere)θ(sin(θ),cos(θ))
(y1,y2)arctan2(y1,y2)

Teorik olarak, aletiniz atan2bir katman fonksiyonu olarak destekleniyorsa (tam olarak 2 giriş alarak ve 1 çıktı üreterek) doğrudan açılarla eşdeğer şekilde çalışabilirsiniz . TensorFlow bunu şimdi yapıyor ve bu kullanım için tasarlanmamış olmasına rağmen üzerinde degrade inişini destekliyor . out = atan2(sigmoid(ylogit), sigmoid(xlogit)) Kayıp fonksiyonu ile araştırdım min((pred - out)^2, (pred - out - 2pi)^2). outs = tanh(ylogit), outc = tanh(xlogit)) Kayıp fonksiyonu ile kullanmaktan çok daha kötü eğitildiğini gördüm 0.5((sin(pred) - outs)^2 + (cos(pred) - outc)^2. Hangi degrade için süreksiz olmak atfedilebilir düşünüyorumatan2

Buradaki testim bunu bir ön işleme işlevi olarak çalıştırıyor

Bunu değerlendirmek için bir görev tanımladım:

Boş bir arka plan üzerinde tek bir çizgiyi temsil eden siyah beyaz bir görüntü verildiğinde Bu çizginin "pozitif x eksenine" hangi açıda olduğunu gösterin

Bu görüntüleri rastgele açılarla rastgele açılarla rastgele bir işlev uyguladım (NB: bu yazının önceki sürümleri rastgele açılar yerine rastgele eğimler kullandı. @Ari Herman sayesinde işaret etti. Şimdi düzeltildi). Görevdeki performansı değerlendirmek için birkaç sinir ağı oluşturdum. Uygulamanın tüm ayrıntıları bu Jupyter not defterinde bulunmaktadır . Kod Julia'da ve Mocha sinir ağı kütüphanesini kullanıyorum.

Karşılaştırma için, 0,1'e ölçeklendirme alternatif yöntemlerine karşı sunuyorum. ve 500 kutuya koymak ve yumuşak etiketli softmax kullanmak. Sonuncusundan özellikle memnun değilim ve ince ayar yapmam gerektiğini hissediyorum. Bu yüzden, diğerlerinden farklı olarak, sadece 1000 yineleme için deniyorum, 1000 ve 10.000 için çalıştırılan diğer ikisi

Deneysel kurulum

Görüntüler piksel, çizgi ortada ve kenara doğru gidiyordu. Görüntü hiçbir gürültü vb, beyaz zemin üzerine, sadece "siyah" bir çizgi vardı.101×101

Her iz için 1000 eğitim ve 1000 test görüntüsü rastgele oluşturuldu.

Değerlendirme ağının tek bir gizli genişliği 500 tabakası vardı. Gizli tabakada Sigmoid nöronları kullanıldı.

0,01 sabit öğrenme oranı ve 0,9 sabit momentum ile Stokastik Gradient Decent tarafından eğitilmiştir.

Düzenleme veya bırakma kullanılmadı. Herhangi bir evrişim vb. Değildi. Umarım bu sonuçlar genelleşir

Bu parametreleri test kodunda değiştirmek çok kolay ve insanları bunu yapmaya teşvik ediyorum. (ve testteki hataları arayın).

Sonuçlar

Sonuçlarım aşağıdaki gibidir:

|                        |  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%       |

Hataya atıfta bulunduğumda, bu, sinir ağı tarafından açı çıkışı ile gerçek açı arasındaki farkın mutlak değeridir. Yani ortalama hata (örneğin) bu farkın 1000 test vakasının ortalama ortalamasıdır. eşitliğini söyleyerek bir hata yaparak yeniden ölçeklendirmemem gerektiğinden emin değilim ) hatası verir . π7π4π4

Ayrıca, doğruluk düzeyini çeşitli ayrıntı düzeylerinde de sunuyorum. Doğruluk, test vakalarının düzeltildiği kısmıdır. Böylece accuracy_to_point01, çıktının gerçek açının 0,01'i içinde olması doğru sayılmış demektir. Temsillerin hiçbiri mükemmel sonuç alamadı, ancak kayan nokta matematiğinin nasıl çalıştığı göz önüne alındığında bu hiç de şaşırtıcı değil.

Bu yazının geçmişine bakarsanız, sonuçların onlara biraz gürültü yaptığını göreceksiniz, her yeniden çalıştırdığımda biraz farklı. Ancak değerlerin genel sırası ve ölçeği aynı kalır; böylece bazı sonuçlar çıkarmamıza izin verdi.

Tartışma

Softmax ile binning, uygulamada bir şey berbat etmediğimden emin olmadığımı söylediğim gibi, çok kötü performans gösteriyor. Gerçi tahmin oranının üzerinde marjinal bir performans sergiliyor. sadece tahmin ediyor olsaydık, ortalama bir hatasınıπ

Sin / cos kodlaması ölçekli 0-1 kodlamasından önemli ölçüde daha iyi performans gösterir. Gelişme, 1000 eğitim yinelemesinde sin / cos'un çoğu metrikte ölçeklemenin 10.000 yinelemeden 3 kat daha iyi performans göstermesidir.

Bence bu, genellemenin geliştirilmesiyle ilgilidir, çünkü her ikisi de eğitim setinde oldukça benzer ortalama kare hatası alıyor, en az 10.000 yineleme çalıştırıldı.

az çok gerçek bir sayı olabileceği göz önüne alındığında, bu görevde mümkün olan en iyi performans üzerinde kesinlikle bir üst sınır vardır, ancak bu tür meleklerin tümü piksel çözünürlükte farklı çizgiler . Örneğin, 45.0 ve 45.0000001 açılarının her ikisi de bu çözünürlükte aynı görüntüye bağlandığından, hiçbir yöntem her ikisinin de mükemmel bir şekilde doğru olmasını sağlamaz.101×101

Ayrıca bu performansın ötesine geçmek için mutlak ölçekte daha iyi bir sinir ağına ihtiyaç duyulduğu da görülmektedir. Deney düzeneğinde yukarıda özetlenenlerden çok daha basit.

Sonuç.

Günah / cos temsili, burada araştırdığım temsillerin en iyisi gibi görünüyor. Bu mantıklıdır, çünkü siz daire etrafında hareket ederken yumuşak bir değere sahiptir. Ayrıca tersi zarif olan arctan2 ile yapılabilir .

Sunulan görevin, ağ için makul bir zorluk sunma yeteneğinde yeterli olduğuna inanıyorum. Sanırım gerçekten sadece eğrisine uyan eğri yapmayı öğreniyor, bu yüzden belki de çok kolay. Ve belki de daha kötüsü, eşleştirilmiş temsili destekliyor olabilir. Sanmıyorum, ama burada geç oluyor, bu yüzden tekrar kodumu bakmak için davet bir şey kaçırmış olabilir . İyileştirmeler veya alternatif görevler önerin.f(x)=y1y2x


Bu kesinlikle yığın değişiminde aldığım en kapsamlı yanıt. Julia'ya aşina olmadığım için, kodunuzu incelemek benim için zor ... bu nedenle, sonuçlarınızı Python kullanarak çoğaltmaya çalışacağım. Bulguları bugün ya da yarın sonra yayınlayacağım.
Ari Herman

Biniciliğin kötü performans gösterdiğine şaşırmasam da, (0,1) ölçeklemenin (cos, sin) yönteminden daha iyi performans gösterdiğine şaşırdım. Çizgilerinizin yükselişini ve çalışmasını rastgele seçerek örneklerinizi oluşturduğunuzu fark ettim. Bu, bence, açıları düzgün dağılmayan, ancak eğimleri olan çizgiler üretecektir. (Cos, sin) yönteminin bu yüzden daha iyi performans göstermesinin mümkün olması mümkün mü? Hedefleri bronzlaştırırsanız (açı) ne olur?
Ari Herman

rastgele eğim ve rastgele açı hakkında haklısın. ancak tan(angle)tan tüm açılar için tanımlı olmadığından (ör. ) hedeflemenin çok iyi gideceğini düşünmüyorum . Rastgele oluşturulan açılarla tekrar çalıştıracağım ve yayınları düzenleyeceğim. π/4
Lyndon White

Eğer gerçekten yeniden uygulamak istiyorsanız, julia ve numpy arasında ve Mocha ve Caffe arasında bire bir harita olmalıdır. Kodun okunması zor bulduğunuz belirli bir kısmı var mı? Julia kolay anlaşılır bir dil olmalı. Belki de tuhaf bir şey yaptım.
Lyndon White

Kodunuzu okudum ve her şey doğru görünüyor. Yine de, kendi versiyonumu yazmak istedim, çünkü bunu yapmak genellikle öğretici. Uygulamam sizinkinden biraz farklı, bu nedenle sonuçları karşılaştırmak ilginç olacak. Onları önümüzdeki birkaç saat içinde yayınlayacağım.
Ari Herman

5

İşte Lyndon White'ın önerilen kodlamasını ikili bir yaklaşımla karşılaştıran başka bir Python uygulaması . Aşağıdaki kod aşağıdaki çıktıyı üretmiştir:

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

Gördüğünüz gibi, ikili yaklaşım bu oyuncak görevinde takdire değer bir performans sergilerken, kodlaması, tüm eğitim yapılandırmalarında, bazen önemli bir farkla daha iyi performans gösterir. Belirli bir görev daha karmaşık hale gibi kullanmanın yararlarını şüpheli Lyndon Beyaz 'ın temsil fazla belli ediyor.( günah ( θ ) , cos ( θ ) )(günah(θ),marul(θ))(günah(θ),marul(θ))

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

İşte denemenizin Python versiyonum. Uygulamanızın ayrıntılarının çoğunu aynı tuttum, özellikle de aynı görüntü boyutunu, ağ katmanı boyutlarını, öğrenme hızını, momentumu ve başarı metriklerini kullanıyorum.

Test edilen her ağın lojistik nöronları olan bir gizli katmanı (boyut = 500) vardır. Çıkış nöronları belirtildiği gibi doğrusal veya softmax'tır. Bağımsız, rastgele üretilmiş 1.000 eğitim görüntüsü ve 1000 test görüntüsü kullandım (böylece tekrarlar olabilir). Eğitim, eğitim seti aracılığıyla 50 iterasyondan oluşuyordu.

Binning ve "gaussian" kodlamayı (oluşturduğum bir isim; hedef çıktı vektörünün exp (-pi * ([1,2,3, ...) biçiminde olması dışında binning'e benzer şekilde kullanarak oldukça iyi bir doğruluk elde edebildim. , 500] - idx) ** 2) burada idx doğru açıya karşılık gelen dizindir). Kod aşağıdadır; sonuçlarım:

(Cos, sin) kodlaması için test hatası:

1.000 egzersiz görüntüsü, 1.000 test görüntüsü, 50 yineleme, doğrusal çıktı

  • Ortalama: 0.0911558142071

  • Ortalama: 0.0429723541743

  • Minimum: 2.77769843793e-06

  • Maksimum: 6.2608513539

  • 0,1: 85,2% hassasiyet

  • 0.01'e kadar doğruluk:% 11.6

  • 0.001:% 1.0 hassasiyet

[-1,1] kodlaması için test hatası:

1.000 egzersiz görüntüsü, 1.000 test görüntüsü, 50 yineleme, doğrusal çıktı

  • Ortalama: 0.234181700523

  • Ortalama: 0.17460197307

  • Minimum: 0.000473665840258

  • Maksimum: 6.00637777237

  • 0,1: 29,9% hassasiyet

  • 0.01'e doğruluk:% 3.3

  • 0.001:% 0.1 hassasiyet

1/500 kodlama için test hatası:

1.000 egzersiz görüntüsü, 1.000 test görüntüsü, 50 iterasyon, softmax çıktı

  • Ortalama: 0.0298767021922

  • Ortalama: 0.00388858079174

  • Minimum: 4.08712407829e-06

  • Maksimum: 6.2784479965

  • 0,1:% 99,6 hassasiyet

  • 0.01'e doğruluk:% 88.9

  • 0.001:% 13.5 hassasiyet

Gauss kodlaması için test hatası:

1.000 egzersiz görüntüsü, 1.000 test görüntüsü, 50 iterasyon, softmax çıktı

  • Ortalama: 0.0296905377463
  • Ortalama: 0.00365867335107
  • Minimum: 4.08712407829e-06
  • Maksimum: 6.2784479965
  • 0,1:% 99,6 hassasiyet
  • 0.01'e doğruluk:% 90.8
  • 0.001:% 14.3 hassasiyet

Sonuçlarımızın neden birbiriyle çeliştiğini anlayamıyorum, ancak daha fazla araştırmaya değer görünüyor.

# -*- 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)

Serin, Anahtar farklı. Her görüntü için yalnızca bir kez egzersiz yapıyorsunuz. Her görüntü için 1.000 kez veya 10.000 kez eğitim alıyorum. Eğitim verileri olsa da çok sayıda yineleme, özellikle de nispeten küçük miktarlarda veriler üzerinde eğitim yaparken normaldir (ve bunu öğrenmek için sadece bir tane yayınlanamaz lisans tezi aldı, ancak bu başka bir hikaye). Bununla birlikte, tablonuza 1 iter sütunu eklemeliyim. bilgilendirici olur
Lyndon White

Benzer hedeflere sahip benzer (ancak özdeş olmayan) görüntüler üzerinde eğitimin bu ağı benzer şekilde etkileyeceğini düşünüyorum. Bu doğruysa, üzerinde çalışılan rastgele görüntü sayısını artırmak için daha iyi çalışmalı, daha küçük bir eğitim seti ile birçok kez tekrarlanmalıdır. Böyle olmadığını mı söylüyorsun?
Ari Herman

Bu benzerdir, ancak bu örnek görev için, sonunda tüm olası görüntüleri göstereceğiniz sorunu yoktur, böylece testiniz treninizle çakışır, böylece test genellemesi çalışmaz. Daha da önemlisi 100.000 egzersiz görüntüsü (1000 * 1000 egzersiz görüntüsü * Yineleme) yapabilirsiniz.
Lyndon White

Haklısın, bu sorunu çözeceğim. Kodumda daha da önemli bir sorun var: (cos, sin) gösteriminin gerektirdiği negatif değerleri üretemeyen lojistik nöronlar kullanıyorum. D'oh! Kodumu gözden geçireceğim ve en kısa zamanda yeniden gönderiyorum.
Ari Herman

(Daha önce yapmadıysanız) , küçük bir hata yapmak ve ağınızın çoğunlukla çalışmasını sağlamak çok kolay olduğundan, sinir ağlarını sıfırdan uyguladığınızda faydalı olan bir Graident Check yapmakla ilgilenebilirsiniz . Re: Neuron: evet, sigmoid gizli katmanın üzerine doğrusal bir çıkış katmanım var
Lyndon White

1

Açıyı kodlamanın başka bir yolu, iki değerden oluşan bir settir:

y1 = maks. (0, teta)

y2 = maks. (0, -tata)

theta_out = y1 - y2

Degrade = 0'da tanımlanmamış olması nedeniyle arctan2'ye benzer bir sorun olurdu. Bir ağı eğitmek ve diğer kodlamalarla karşılaştırmak için zamanım yok ama bu makalede teknik oldukça başarılı görünüyordu.


1
Bu, bir gönderideki başka bir soru ile karıştırılmış bir cevap gibi görünüyor. Bu site forumdan biraz farklı çalışıyor. Burada cevaplar orijinal soruyu cevaplamaya odaklanmalıdır. Ve başka bir sorunuz veya yorumunuz varsa - bu şekilde gönderilmelidir.
Karolis Koncevičius
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.