Mã hóa dữ liệu góc cho mạng thần kinh


20

Tôi đang đào tạo một mạng lưới thần kinh (chi tiết không quan trọng) trong đó dữ liệu đích là một vectơ góc (trong khoảng từ 0 đến 2 * pi). Tôi đang tìm kiếm lời khuyên về cách mã hóa dữ liệu này. Đây là những gì tôi hiện đang cố gắng (với thành công hạn chế):

1) Mã hóa 1 of C: Tôi ghép các góc có thể thiết lập thành 1000 góc riêng biệt hoặc sau đó chỉ ra một góc cụ thể bằng cách đặt 1 ở chỉ số liên quan. Vấn đề với điều này là mạng chỉ đơn giản là học cách xuất tất cả 0 (vì điều này gần như chính xác).

2) Chia tỷ lệ đơn giản: Tôi chia tỷ lệ phạm vi đầu ra của mạng ([0,1]) thành [0,2 * pi]. Vấn đề ở đây là các góc tự nhiên có cấu trúc liên kết tròn (tức là 0,0001 và 2 * pi thực sự nằm ngay cạnh nhau). Với loại mã hóa này, thông tin đó sẽ bị mất.

Mọi lơi đê nghị đêu nên được đanh gia cao!


1
Bạn không nên gặp vấn đề với mạng xuất ra tất cả các số không, nếu bạn sử dụng lớp đầu ra softmax - điều mà bạn thường nên làm, nếu bạn đang sử dụng đầu ra catagorical (tức là 1-C).
Lyndon White

7
Một ý tưởng mã hóa hoàn toàn đầu cơ (tôi chưa thấy nó được thực hiện hoặc thử nghiệm nó, nhưng tôi chưa nhìn thấy) là mã hóa góc của bạn ( ) thành một cặp: . Tôi nghĩ sau đó nó sẽ là một bản đồ liên tục với tất cả các giá trị như và gần nhau. Tôi nghĩ rằng tôi có thể xây dựng một bản demo của điều này và thử nghiệm nó. θ ( tội lỗi ( θ ) , cos ( θ ) ) 0 2 πθθ(tội(θ),cos(θ))02π
Lyndon White

Tôi đã suy nghĩ về điều này nhiều hơn và tôi nghĩ rằng nó thực sự có thể là tất cả trong chức năng mất của bạn. Tôi muốn thử một loạt các thứ. Tôi đã làm bản demo, nhưng không hoàn thành bài kiểm tra về nó. Mong đợi một câu trả lời chi tiết với sự ủng hộ thử nghiệm vào ngày mai đôi khi. (Chọc tôi nếu tôi không)
Lyndon White

Tôi hiện không sử dụng lớp softmax, và đó có lẽ là vấn đề. Tôi sẽ thực hiện điều đó ngay hôm nay nếu tôi có cơ hội! Ý tưởng (cos, sin) của bạn rất thú vị và tôi đặc biệt thích nó tự động đưa phạm vi đó vào [-1,1] (tốt nếu bạn đang làm việc với chức năng kích hoạt tanh). Tôi mong muốn được nhìn thấy kết quả của bạn1
Ari Herman

Cập nhật nhanh: Tôi đã thử triển khai lớp softmax và vẫn không gặp may. Vấn đề, tôi nghĩ, là đối với vấn đề này, điều cốt yếu là "độ góc" của dữ liệu được thể hiện bằng cách nào đó trong mã hóa. Với mã hóa phân loại, cấu trúc liên kết của dữ liệu đích bị mất. Do đó, lỗi 0,5 * pi và 0,05 * pi trông giống nhau đối với mạng (nó xem cả hai là phân loại không chính xác).
Ari Herman

Câu trả lời:


18

Giới thiệu

Tôi thấy câu hỏi này thực sự thú vị, tôi cho rằng ai đó đã đưa ra một bài báo về nó, nhưng đó là ngày nghỉ của tôi, vì vậy tôi không muốn theo đuổi các tài liệu tham khảo.

Vì vậy, chúng tôi có thể coi nó như là một đại diện / mã hóa đầu ra, mà tôi làm trong câu trả lời này. Tôi vẫn nghĩ rằng có một cách tốt hơn, nơi bạn chỉ có thể sử dụng một chức năng mất hơi khác nhau. (Có lẽ tổng các khác biệt bình phương, sử dụng phép trừ modulo 2 ).π

Nhưng trở đi với câu trả lời thực tế.

phương pháp

Tôi đề xuất rằng một góc được biểu diễn dưới dạng một cặp giá trị, sin và cos của nó.θ

Vì vậy, chức năng mã hóa là: và chức năng giải mã là: Vì arctan2 là tiếp tuyến nghịch đảo, giữ nguyên hướng trong tất cả các góc phần tư)θ(sin(θ),cos(θ))
(y1,y2)arctan2(y1,y2)

Về lý thuyết, bạn có thể làm việc tương đương trực tiếp với các góc nếu công cụ của bạn sử dụng được hỗ trợ atan2như một chức năng lớp (lấy chính xác 2 đầu vào và tạo ra 1 đầu ra). TensorFlow thực hiện điều này ngay bây giờ và hỗ trợ giảm độ dốc trên nó , mặc dù nó không dành cho mục đích sử dụng này. Tôi đã điều tra bằng cách sử dụng out = atan2(sigmoid(ylogit), sigmoid(xlogit)) với một chức năng mất min((pred - out)^2, (pred - out - 2pi)^2). Tôi thấy rằng nó được đào tạo tồi tệ hơn nhiều so với việc sử dụng outs = tanh(ylogit), outc = tanh(xlogit)) với chức năng mất 0.5((sin(pred) - outs)^2 + (cos(pred) - outc)^2. Mà tôi nghĩ có thể được quy cho độ dốc không liên tục choatan2

Thử nghiệm của tôi ở đây chạy nó như là một chức năng tiền xử lý

Để đánh giá điều này tôi đã xác định một nhiệm vụ:

Đưa ra một hình ảnh đen trắng đại diện cho một dòng trên nền trống Xuất ra góc nào của đường thẳng đó với "trục x dương"

Tôi đã triển khai một chức năng tạo ngẫu nhiên các hình ảnh này, với các đường ở các góc ngẫu nhiên (NB: các phiên bản trước của bài đăng này đã sử dụng độ dốc ngẫu nhiên, thay vì các góc ngẫu nhiên. Cảm ơn @Ari Herman đã chỉ ra. Bây giờ nó đã được sửa). Tôi đã xây dựng một số mạng lưới thần kinh để đánh giá hiệu suất trong nhiệm vụ. Các chi tiết đầy đủ của việc thực hiện là trong máy tính xách tay Jupyter này . Mã này là tất cả trong Julia , và tôi sử dụng thư viện mạng thần kinh Mocha .

Để so sánh, tôi trình bày nó dựa trên các phương pháp thay đổi tỷ lệ thành 0,1. và bỏ vào 500 thùng và sử dụng softmax nhãn mềm. Tôi không đặc biệt hài lòng với điều cuối cùng, và cảm thấy tôi cần phải điều chỉnh nó. Đó là lý do tại sao, không giống như những cái khác tôi chỉ dùng thử trong 1.000 lần lặp, so với hai lần khác được chạy cho 1.000 và cho 10.000

Thiết lập thử nghiệm

101×101

Đối với mỗi đường đào tạo 1.000 và 1.000 hình ảnh thử nghiệm được tạo ngẫu nhiên.

Mạng đánh giá có một lớp ẩn duy nhất có chiều rộng 500. Các nơ-ron Sigmoid được sử dụng trong lớp ẩn.

Nó được đào tạo bởi Stochastic Gradient Decent, với tỷ lệ học tập cố định là 0,01 và động lượng cố định là 0,9.

Không có chính quy, hoặc bỏ học đã được sử dụng. Cũng không phải là bất kỳ loại tích chập nào, v.v. Một mạng đơn giản, mà tôi hy vọng gợi ý rằng những kết quả này sẽ tổng quát hóa

Rất dễ dàng để điều chỉnh các tham số này trong mã kiểm tra và tôi khuyến khích mọi người làm như vậy. (và tìm lỗi trong bài kiểm tra).

Các kết quả

Kết quả của tôi như sau:

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

7π4π4

Tôi cũng trình bày độ chính xác ở các mức độ chi tiết khác nhau. Độ chính xác là một phần của các trường hợp thử nghiệm đã được sửa. Vì vậy, accuracy_to_point01có nghĩa là nó được tính là chính xác nếu đầu ra nằm trong 0,01 của góc thực. Không đại diện nào có kết quả hoàn hảo, nhưng điều đó không có gì đáng ngạc nhiên khi toán học dấu phẩy động hoạt động như thế nào.

Nếu bạn nhìn vào lịch sử của bài đăng này, bạn sẽ thấy kết quả có một chút nhiễu với họ, hơi khác nhau mỗi lần tôi chạy lại nó. Nhưng thứ tự và quy mô chung của các giá trị vẫn giữ nguyên; do đó cho phép chúng tôi rút ra một số kết luận.

Thảo luận

π

Mã hóa sin / cos thực hiện tốt hơn đáng kể so với mã hóa 0-1 được chia tỷ lệ. Sự cải thiện là ở mức độ 1.000 lần lặp đào tạo sin / cos đang thực hiện tốt hơn khoảng 3 lần trên hầu hết các số liệu so với tỷ lệ là 10.000 lần lặp.

Tôi nghĩ, một phần điều này có liên quan đến việc cải thiện khái quát hóa, vì cả hai đều nhận được lỗi bình phương trung bình khá giống nhau trên tập huấn luyện, ít nhất một lần 10.000 lần lặp được chạy.

101×101

Dường như ở một quy mô tuyệt đối để vượt ra ngoài hiệu suất này, cần có một mạng lưới thần kinh tốt hơn. Thay vì rất đơn giản được nêu ở trên trong thiết lập thử nghiệm.

Phần kết luận.

Dường như đại diện sin / cos là tốt nhất, trong số các đại diện tôi đã điều tra ở đây. Điều này có ý nghĩa, trong đó nó có một giá trị trơn tru khi bạn di chuyển xung quanh vòng tròn. Tôi cũng thích rằng nghịch đảo có thể được thực hiện với arctan2 , đó là thanh lịch.

f(x)= =y1y2x


Đây chắc chắn là phản hồi kỹ lưỡng nhất mà tôi từng nhận được khi trao đổi stack. Vì tôi không quen thuộc với Julia, tôi rất khó kiểm tra mã của bạn ... vì vậy, thay vào đó tôi sẽ cố gắng sao chép kết quả của bạn bằng Python. Tôi sẽ đăng cho tôi những phát hiện sau hôm nay hoặc ngày mai.
Ari Herman

Mặc dù tôi không ngạc nhiên khi binning hoạt động kém, tôi đã ngạc nhiên ở mức độ (0,1) tỷ lệ vượt trội so với phương pháp (cos, sin). Tôi nhận thấy rằng bạn đã tạo các ví dụ của mình bằng cách chọn ngẫu nhiên sự tăng và chạy của các dòng. Điều này, theo tôi sẽ tạo ra các đường có góc không được phân bố đồng đều, nhưng có độ dốc. Có thể đây là lý do tại sao phương thức (cos, sin) thực hiện tốt hơn nhiều như vậy? Điều gì sẽ xảy ra nếu bạn thực hiện các mục tiêu tan (góc) ...?
Ari Herman

tan(angle)π/4

Cần có một bản đồ gần một đến một giữa julia và numpy, và giữa Mocha và Caffe, nếu bạn thực sự muốn thực hiện lại nó. Có một phần đặc biệt nào của mã mà bạn cảm thấy khó đọc không? Julia nên là một ngôn ngữ dễ hiểu. Vì vậy, có lẽ tôi đã làm một cái gì đó kỳ lạ.
Lyndon White

Tôi cuối cùng đã đọc mã của bạn, và mọi thứ dường như chính xác. Tuy nhiên, tôi muốn viết phiên bản của riêng mình, vì làm như vậy thường mang tính hướng dẫn. Việc thực hiện của tôi hơi khác so với bạn, vì vậy sẽ rất thú vị khi so sánh kết quả. Tôi sẽ đăng chúng trong vài giờ tới.
Ari Herman

5

Đây là một triển khai Python khác so sánh mã hóa được đề xuất của Lyndon White với cách tiếp cận có giá trị. Mã dưới đây tạo ra đầu ra sau:

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

(tội(θ),cos(θ))(tội(θ),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

Đây là phiên bản Python của thí nghiệm của bạn. Tôi giữ nhiều chi tiết về việc triển khai của bạn giống nhau, đặc biệt tôi sử dụng cùng kích thước hình ảnh, kích thước lớp mạng, tốc độ học tập, động lượng và số liệu thành công.

Mỗi mạng được kiểm tra có một lớp ẩn (size = 500) với các nơ-ron logistic. Các tế bào thần kinh đầu ra là tuyến tính hoặc softmax như đã lưu ý. Tôi đã sử dụng 1.000 hình ảnh đào tạo và 1.000 hình ảnh thử nghiệm được tạo độc lập, được tạo ngẫu nhiên (vì vậy có thể có các lần lặp lại). Đào tạo bao gồm 50 lần lặp thông qua tập huấn luyện.

Tôi đã có thể có được độ chính xác khá tốt khi sử dụng mã hóa binning và "gaussian" (tên tôi tạo ra, tương tự như binning ngoại trừ vectơ đầu ra đích có dạng exp (-pi * ([1,2,3, ... , 500] - idx) ** 2) trong đó idx là chỉ số tương ứng với góc chính xác). Mã dưới đây; đây là kết quả của tôi

Kiểm tra lỗi cho mã hóa (cos, sin):

1.000 hình ảnh đào tạo, 1.000 hình ảnh thử nghiệm, 50 lần lặp, đầu ra tuyến tính

  • Có nghĩa là: 0,0911558142071

  • Trung vị: 0,0429723541743

  • Tối thiểu: 2.77769843793e-06

  • Tối đa: 6.2608513539

  • Độ chính xác đến 0,1: 85,2%

  • Độ chính xác đến 0,01: 11,6%

  • Độ chính xác đến 0,001: 1,0%

Lỗi kiểm tra mã hóa [-1,1]:

1.000 hình ảnh đào tạo, 1.000 hình ảnh thử nghiệm, 50 lần lặp, đầu ra tuyến tính

  • Có nghĩa là: 0,234181700523

  • Trung vị: 0,17460197307

  • Tối thiểu: 0,000473665840258

  • Tối đa: 6,00637777237

  • Độ chính xác đến 0,1: 29,9%

  • Độ chính xác đến 0,01: 3,3%

  • Độ chính xác đến 0,001: 0,1%

Lỗi kiểm tra mã hóa 1 trên 500:

1.000 hình ảnh đào tạo, 1.000 hình ảnh thử nghiệm, 50 lần lặp, đầu ra softmax

  • Có nghĩa là: 0,0298767021922

  • Trung bình: 0,00388858079174

  • Tối thiểu: 4.08712407829e-06

  • Tối đa: 6.2784479965

  • Độ chính xác đến 0,1: 99,6%

  • Độ chính xác đến 0,01: 88,9%

  • Độ chính xác đến 0,001: 13,5%

Lỗi kiểm tra mã hóa gaussian:

1.000 hình ảnh đào tạo, 1.000 hình ảnh thử nghiệm, 50 lần lặp, đầu ra softmax

  • Có nghĩa là: 0,0296905377463
  • Trung bình: 0,00365867335107
  • Tối thiểu: 4.08712407829e-06
  • Tối đa: 6.2784479965
  • Độ chính xác đến 0,1: 99,6%
  • Độ chính xác đến 0,01: 90,8%
  • Độ chính xác đến 0,001: 14,3%

Tôi không thể hiểu tại sao kết quả của chúng tôi dường như mâu thuẫn với nhau, nhưng có vẻ đáng để điều tra thêm.

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

Mát mẻ, Trên phím khác nhau. Bạn chỉ được đào tạo trên mỗi hình ảnh một lần. Tôi đang đào tạo trên mỗi hình ảnh 1.000 lần, hoặc 10.000 lần. Nhiều lần lặp mặc dù dữ liệu đào tạo là bình thường, đặc biệt là khi đào tạo trên một lượng dữ liệu tương đối nhỏ (và tôi chỉ mất một luận án nâng cấp không thể công bố để tìm hiểu điều này, nhưng đó là một câu chuyện khác). Như đã nói, tôi nên thêm một cột 1 iter vào bảng của mình. đó sẽ là thông tin
Lyndon White

Tôi nghĩ rằng việc đào tạo trên các hình ảnh tương tự (nhưng không giống hệt nhau) với các mục tiêu tương tự sẽ ảnh hưởng đến mạng đó tương tự. Nếu đó là sự thật, nó sẽ hoạt động tốt khi chỉ cần tăng số lượng hình ảnh ngẫu nhiên được đào tạo, thay vì lặp đi lặp lại nhiều lần thông qua một tập huấn luyện nhỏ hơn. Bạn đang nói đây không phải là trường hợp?
Ari Herman

Nó cũng tương tự, nhưng đối với tác vụ ví dụ này, vấn đề là cuối cùng bạn sẽ hiển thị tất cả các hình ảnh có thể để bài kiểm tra của bạn trùng với tàu của bạn, vì vậy việc kiểm tra tổng quát sẽ không hiệu quả. Đáng kể hơn mặc dù bạn thực hiện 100.000 hình ảnh đào tạo, đó là <1000 * 1000 hình ảnh đào tạo * Lặp lại.
Lyndon White

Bạn đã đúng, tôi sẽ khắc phục vấn đề đó. Có một vấn đề thậm chí còn quan trọng hơn với mã của tôi: Tôi đang sử dụng các nơ-ron logistic không có khả năng tạo ra các giá trị âm theo yêu cầu của biểu diễn (cos, sin). Ôi! Tôi sẽ sửa đổi mã của mình và đăng lại càng sớm càng tốt.
Ari Herman

Bạn có thể (nếu bạn chưa làm như vậy) quan tâm đến việc thực hiện Kiểm tra Graident , điều này đáng giá khi triển khai mạng thần kinh từ đầu, vì rất dễ mắc lỗi nhỏ và mạng của bạn vẫn hoạt động chủ yếu. Re: Neuron: yeah, tôi có một lớp đầu ra tuyến tính, trên lớp ẩn sigmoid
Lyndon White

1

Một cách khác để mã hóa góc là một bộ gồm hai giá trị:

y1 = tối đa (0, theta)

y2 = tối đa (0, -theta)

theta thừng = y1 - y2

Điều này sẽ có vấn đề tương tự như arctan2 ở chỗ độ dốc không được xác định tại theta = 0. Tôi không có thời gian để đào tạo một mạng và so sánh với các mã hóa khác nhưng trong bài báo này , kỹ thuật này có vẻ thành công một cách hợp lý.


1
Đây có vẻ như là một câu trả lời trộn lẫn với một câu hỏi khác trong một bài. Trang web này hoạt động một chút khác với cách diễn đàn. Ở đây câu trả lời nên tập trung vào việc trả lời câu hỏi ban đầu. Và nếu bạn có một câu hỏi hoặc một bình luận khác - nó nên được đăng như vậy.
Karolis Koncevičius
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.