तंत्रिका नेटवर्क के लिए कोण डेटा एन्कोडिंग


20

मैं एक तंत्रिका नेटवर्क (विवरण महत्वपूर्ण नहीं) का प्रशिक्षण ले रहा हूं जहां लक्ष्य डेटा कोणों (0 और 2 * पीआई के बीच) का वेक्टर है। मैं इस डेटा को एन्कोड करने की सलाह के लिए देख रहा हूँ। यहाँ मैं वर्तमान में (सीमित सफलता के साथ) कोशिश कर रहा हूँ:

1) 1-सी-सी एन्कोडिंग: मैं संभव कोणों को 1000 या इतने असतत कोणों में सेट करता हूं और फिर संबंधित सूचकांक पर 1 डालकर एक विशेष कोण को इंगित करता हूं। इसके साथ समस्या यह है कि नेटवर्क केवल सभी 0 को आउटपुट करना सीखता है (क्योंकि यह लगभग बिल्कुल सही है)।

2) सरल स्केलिंग: मैंने नेटवर्क आउटपुट रेंज ([0,1]) को [0,2 * pi] तक बढ़ाया। यहाँ समस्या यह है कि कोणों में स्वाभाविक रूप से एक गोलाकार टोपोलॉजी होती है (यानी 0.0001 और 2 * पाई वास्तव में एक दूसरे के ठीक बगल में होती है)। इस प्रकार के एन्कोडिंग के साथ, वह जानकारी खो जाती है।

किसी भी सुझाव की सराहना की जाएगी!


1
अगर आप सॉफ्टमैक्स आउटपुट लेयर का उपयोग करते हैं - जो कि आपको आम तौर पर करना चाहिए, यदि आप एक कैटागोरिकल (यानी 1-ऑफ-सी) आउटपुट का उपयोग कर रहे हैं, तो आपको नेटवर्क के सभी शून्य के साथ कोई समस्या नहीं होनी चाहिए।
लिंडन व्हाइट

7
विशुद्ध रूप से सट्टा एन्कोडिंग विचार (मैंने इसे नहीं देखा है या इसका परीक्षण नहीं किया है, लेकिन मैंने नहीं देखा है) एक कोण के रूप में आपके कोण ( ) को एक जोड़ी के रूप में एन्कोड किया गया है: । मुझे लगता है कि यह और जैसे सभी मूल्यों के साथ एक निरंतर मानचित्र होगा । मुझे लगता है कि मैं इसका डेमो बना सकता हूं और इसका परीक्षण कर सकता हूं। θ ( पाप ( θ ) , क्योंकि ( θ ) ) 0 2 πθθ(sin(θ),cos(θ))02π
लिंडन व्हाइट

मैं इस बारे में कुछ और सोच रहा हूँ, और मुझे लगता है कि यह वास्तव में jsut हो सकता है आपके सभी फंक्शन में। मैं चीजों का एक गुच्छा कोशिश करना चाहता हूं। मैंने डेमो बनाया, लेकिन उस पर परीक्षण पूरा नहीं किया। कल किसी समय प्रायोगिक समर्थन के साथ एक विस्तृत उत्तर की अपेक्षा करें। (अगर मुझे नहीं लगता है तो मुझे रोकें)
लिंडन व्हाइट

मैं वर्तमान में सॉफ्टमैक्स परत का उपयोग नहीं कर रहा हूं, और शायद यही समस्या है। अगर आज मुझे मौका मिला तो मैं इसे लागू करूँगा! आपका (कॉस, पाप) विचार बहुत दिलचस्प है और मुझे विशेष रूप से यह पसंद है कि यह स्वचालित रूप से उस रेंज को [-1,1] में डाल देता है (अच्छा है अगर आप एक तन सक्रियण फ़ंक्शन के साथ काम कर रहे हैं)। मैं आपके परिणामों को देखने के लिए उत्सुक हूं ।1
अरी हरमन

एक त्वरित अद्यतन: मैंने एक सॉफ्टमैक्स परत को लागू करने की कोशिश की, और अभी भी कोई भाग्य नहीं है। मुझे लगता है कि समस्या यह है कि इस समस्या के लिए यह आवश्यक है कि एन्कोडिंग में किसी भी तरह से डेटा की "कोणीयता" का प्रतिनिधित्व किया जाए। एक श्रेणीबद्ध एन्कोडिंग के साथ, लक्ष्य डेटा की टोपोलॉजी खो जाती है। इसलिए 0.5 * pi और 0.05 * pi की त्रुटि नेटवर्क के समान है (यह दोनों को गलत वर्गीकरण के रूप में देखता है)।
अरी हरमन

जवाबों:


18

परिचय

मुझे यह प्रश्न वास्तव में दिलचस्प लगता है, मुझे लगता है कि किसी ने इस पर एक पेपर डाल दिया है, लेकिन यह मेरा दिन है, इसलिए मैं संदर्भों का पीछा नहीं करना चाहता।

इसलिए हम इसे आउटपुट के प्रतिनिधित्व / एन्कोडिंग के रूप में मान सकते हैं, जो मैं इस उत्तर में करता हूं। मैं सोच रहा हूं कि एक बेहतर तरीका है, जहां आप बस थोड़ा अलग नुकसान फ़ंक्शन का उपयोग कर सकते हैं। (संभवतया स्क्वेरड अंतर का योग, घटाव modulo 2 का उपयोग करके )।π

लेकिन वास्तविक जवाब के साथ।

तरीका

मेरा प्रस्ताव है कि एक कोण को मूल्यों की एक जोड़ी, उसके साइन और उसके कोसाइन के रूप में दर्शाया जाए।θ

तो एन्कोडिंग फ़ंक्शन है: और डिकोडिंग फ़ंक्शन है: के लिए arctan2 उलटा स्पर्शरेखा किया जा रहा है, सभी चतुर्थ भाग में दिशा संरक्षण)θ(sin(θ),cos(θ))
(y1,y2)arctan2(y1,y2)

आप सिद्धांत रूप में, कोण के साथ सीधे काम कर सकते हैं यदि आपका उपकरण atan2एक परत फ़ंक्शन के रूप में समर्थित है (ठीक 2 इनपुट ले रहा है और इसका आउटपुट उत्पादन कर रहा है)। 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

यहां मेरा परीक्षण इसे प्रीप्रोसेसिंग फ़ंक्शन के रूप में चलाता है

इसका मूल्यांकन करने के लिए मैंने एक कार्य को परिभाषित किया:

एक काले और सफेद छवि को देखते हुए एक रिक्त पृष्ठभूमि पर एक लाइन का उत्पादन आउटपुट क्या कोण है कि लाइन "सकारात्मक एक्स-अक्ष" पर है

मैंने एक फ़ंक्शन को यादृच्छिक रूप से इन छवियों को कार्यान्वित किया, यादृच्छिक कोणों पर लाइनों के साथ (एनबी: इस पोस्ट के पहले संस्करणों ने यादृच्छिक कोणों के बजाय यादृच्छिक कोणों का उपयोग किया था। बिंदु के लिए @Ari हरमन को धन्यवाद। यह अब तय हो गया है)। मैंने कार्य पर प्रदर्शन के मूल्यांकन के लिए कई तंत्रिका नेटवर्क का निर्माण किया। कार्यान्वयन का पूरा विवरण इस बृहस्पति नोटबुक में है । कोड सभी जूलिया में है , और मैं मोचा न्यूरल नेटवर्क लाइब्रेरी का उपयोग करता हूं ।

तुलना के लिए, मैं इसे स्केलिंग के वैकल्पिक तरीकों के खिलाफ 0,1 पर प्रस्तुत करता हूं। और 500 डिब्बे में डालने और सॉफ्ट-लेबल सॉफ्टमैक्स का उपयोग करना। मैं अंतिम रूप से विशेष रूप से खुश नहीं हूं, और मुझे लगता है कि मुझे इसे मोड़ने की आवश्यकता है। यही कारण है कि, दूसरों के विपरीत मैं केवल 1,000 पुनरावृत्तियों के लिए इसका परीक्षण करता हूं, अन्य दो बनाम जो 1,000 और 10,000 के लिए चलाए गए थे

प्रयोगिक व्यवस्था

केंद्र में लाइन शुरू होने और किनारे पर जाने के साथ छवियां पिक्सेल थीं । छवि में कोई शोर आदि नहीं था, बस एक "काली" रेखा थी, एक सफेद पृष्ठभूमि पर।101×101

प्रत्येक निशान के लिए 1,000 प्रशिक्षण, और 1,000 परीक्षण छवियों को यादृच्छिक रूप से उत्पन्न किया गया था।

मूल्यांकन नेटवर्क में चौड़ाई 500 की एक छिपी हुई परत थी। छिपी हुई परत में सिग्माइड न्यूरॉन्स का उपयोग किया गया था।

यह स्टोचस्टिक ग्रेडिएंट डिसेंट द्वारा 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%       |

जहां मैं त्रुटि का संदर्भ देता हूं, यह तंत्रिका नेटवर्क द्वारा कोण आउटपुट और सच्चे कोण के बीच अंतर का पूर्ण मूल्य है। तो माध्य त्रुटि (उदाहरण के लिए) इस अंतर के 1,000 परीक्षण मामलों में औसत है आदि। मुझे यकीन नहीं है कि मुझे यह कहना मुश्किल नहीं होना चाहिए कि त्रुटि का बराबर होना चाहिए ) की त्रुटि के लिए । π7π4π4

मैं भी विभिन्न स्तर पर सटीकता को प्रस्तुत करता हूं। सटीकता के परीक्षण के मामलों का हिस्सा होने के कारण यह संबद्ध हो गया। तो accuracy_to_point01इसका मतलब है कि यह सही माना जाता था यदि आउटपुट सच्चे कोण से 0.01 के भीतर था। किसी भी अभ्यावेदन का कोई पूर्ण परिणाम नहीं मिला, लेकिन यह बिल्कुल आश्चर्यजनक नहीं है कि फ्लोटिंग पॉइंट गणित कैसे काम करता है।

यदि आप इस पोस्ट के इतिहास पर एक नज़र डालते हैं, तो आप देखेंगे कि परिणाम उनके पास थोड़ा शोर करते हैं, हर बार जब मैं इसे पुन: करता हूं तो थोड़ा अलग होता है। लेकिन मूल्यों का सामान्य क्रम और पैमाना समान रहता है; इस प्रकार हमें कुछ निष्कर्ष निकालने की अनुमति मिलती है।

विचार-विमर्श

सॉफ्टमैक्स के साथ बाइनिंग सबसे खराब प्रदर्शन करता है, जैसा कि मैंने कहा कि मुझे यकीन नहीं है कि मैंने कार्यान्वयन में कुछ पेंच नहीं किया है। हालांकि यह अनुमान दर से थोड़ा ऊपर है। अगर यह सिर्फ अनुमान लगा रहे थे कि हम की औसत त्रुटि प्राप्त करेंगेπ

पाप / कॉस एन्कोडिंग स्केलिंग 0-1 एन्कोडिंग की तुलना में काफी बेहतर प्रदर्शन करता है। सुधार इस हद तक है कि 1,000 प्रशिक्षण पुनरावृत्तियों में पाप / कॉस स्केलिंग की तुलना में सबसे अधिक मैट्रिक्स पर लगभग 3 गुना बेहतर प्रदर्शन कर रहा है, 10,000 पुनरावृत्तियों पर है।

मुझे लगता है, भाग में यह सामान्यीकरण में सुधार से संबंधित है, क्योंकि दोनों को प्रशिक्षण सेट पर काफी समान मतलब चुकता त्रुटि मिल रही थी, कम से कम एक बार 10,000 पुनरावृत्तियों को चलाया गया था।

इस कार्य में सर्वोत्तम संभव प्रदर्शन पर निश्चित रूप से एक ऊपरी सीमा है, यह देखते हुए कि एंगल किसी भी वास्तविक संख्या में कम या ज्यादा हो सकता है, लेकिन ऐसे सभी स्वर्गदूत पिक्सल के संकल्प पर विभिन्न लाइनों का उत्पादन नहीं करते हैं । इसलिए, उदाहरण के लिए, कोण ४५.० और ४५.००००००१ दोनों उस संकल्प पर एक ही छवि से बंधे हैं, कोई भी विधि कभी भी दोनों को पूरी तरह से सही नहीं करेगी।101×101

यह भी संभावना है कि इस प्रदर्शन से आगे बढ़ने के लिए एक पूर्ण पैमाने पर, एक बेहतर तंत्रिका नेटवर्क की आवश्यकता है। प्रायोगिक सेटअप में ऊपर बताए गए बहुत ही सरल के बजाय।

निष्कर्ष।

ऐसा लगता है कि पाप / कॉस प्रतिनिधित्व अब तक का सबसे अच्छा है, मैंने यहां जो अभ्यावेदन की जांच की। इससे समझ में आता है, इसमें सर्कल के चारों ओर घूमने के साथ-साथ इसका सहज मूल्य है। मुझे यह भी पसंद है कि व्युत्क्रम arctan2 के साथ किया जा सकता है , जो सुरुचिपूर्ण है।

मेरा मानना ​​है कि प्रस्तुत कार्य नेटवर्क के लिए एक उचित चुनौती पेश करने की क्षमता में पर्याप्त है। हालांकि मुझे लगता है कि वास्तव में यह सिर्फ लिए वक्र फिटिंग करना सीख रहा हैf(x)=y1y2x


यह निश्चित रूप से सबसे गहन प्रतिक्रिया है जो मुझे स्टैक एक्सचेंज पर कभी मिला है। चूंकि मैं जूलिया से परिचित नहीं हूं, इसलिए मेरे लिए आपके कोड की जांच करना मुश्किल है ... इसलिए, इसके बजाय मैं पायथन का उपयोग करके आपके परिणामों को दोहराने की कोशिश करने जा रहा हूं। मैं आज या कल बाद में निष्कर्ष निकालूंगा।
अरी हर्मन

जबकि मुझे आश्चर्य नहीं था कि बिनिंग ने खराब प्रदर्शन किया, मैं उस हद तक आश्चर्यचकित था, जिस पर (0,1) स्केलिंग (कोस, सिन) विधि द्वारा बेहतर प्रदर्शन किया गया था। मैंने देखा कि आपने अपने उदाहरणों को बेतरतीब ढंग से लाइनों के उठने और चलाने के द्वारा उत्पन्न किया। मुझे लगता है कि वे रेखाएँ उत्पन्न करें जिनके कोण समान रूप से वितरित नहीं हैं, लेकिन जिनकी ढलान है। क्या यह संभव है कि यही कारण है कि (cos, sin) पद्धति ने इतना बेहतर प्रदर्शन किया है? क्या होगा अगर आपने टारगेट को टैन (कोण) बना दिया ...?
अरी हरमन

tan(angle)π/4

जूलिया और सुन्न के बीच एक से एक नक्शे के करीब होना चाहिए, और मोचा और कैफ के बीच, यदि आप वास्तव में इसे फिर से लागू करना चाहते हैं। क्या उस कोड का कोई विशेष हिस्सा है जिसे आप पढ़ना मुश्किल समझते हैं? जूलिया को भाषा समझने में आसान होना चाहिए। इसलिए शायद मैंने कुछ अजीब किया है।
लिंडन व्हाइट

मैंने आपका कोड पढ़ना समाप्त कर दिया है, और सब कुछ सही लगता है। फिर भी, मैं अपना खुद का संस्करण लिखना चाहता था, क्योंकि ऐसा करना आमतौर पर शिक्षाप्रद होता है। मेरा कार्यान्वयन आपसे थोड़ा अलग है, इसलिए परिणामों की तुलना करना दिलचस्प होगा। मैं अगले कुछ घंटों में उन्हें पोस्ट करूंगा।
एर हर्मन

5

यहाँ एक और पायथन कार्यान्वयन है, जो लिंडन व्हाइट के प्रस्तावित एन्कोडिंग की तुलना एक बॉनड दृष्टिकोण से करता है। नीचे दिया गया कोड निम्न आउटपुट का उत्पादन करता है:

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 पुनरावृत्तियों शामिल थे।

मैं बिनिंग और "गाऊसी" एन्कोडिंग का उपयोग करके काफी अच्छी सटीकता प्राप्त करने में सक्षम था (एक नाम जो मैंने बनाया था; बिनिंग के समान है कि लक्ष्य आउटपुट वेक्टर में एक्सपी (- * * [1,2,3, ...) है। , 500] - आईडीएक्स) ** 2) जहां आईडी सही कोण के अनुरूप सूचकांक है)। कोड नीचे है; यहाँ मेरे परिणाम हैं:

(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 पुनरावृत्तियों, सॉफ्टमैक्स आउटपुट

  • मीन: 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 पुनरावृत्तियों, सॉफ्टमैक्स आउटपुट

  • मीन: 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 पुनरावृति कॉलम जोड़ना चाहिए। यह जानकारीपूर्ण होगा
Lyndon White

मुझे लगता है कि समान लक्ष्यों के साथ समान (लेकिन समान नहीं) छवियों पर प्रशिक्षण उस नेटवर्क को समान रूप से प्रभावित करेगा। अगर यह सच है, तो बस एक छोटे से प्रशिक्षण सेट के माध्यम से कई बार पुनरावृत्त होने पर यादृच्छिक छवियों की संख्या बढ़ाने के लिए ठीक काम करना चाहिए। क्या आप यह कह रहे हैं कि ऐसा नहीं है?
अरी हरमन

यह समान है, लेकिन इस उदाहरण कार्य के लिए यह समस्या नहीं है कि आखिरकार आप सभी संभव चित्र दिखाएंगे ताकि आपका परीक्षण आपकी ट्रेन के साथ ओवरलैप हो जाए, इसलिए परीक्षण सामान्यीकरण काम नहीं करेगा। अधिक महत्वपूर्ण है कि आप 100,000 प्रशिक्षण चित्र करते हैं, जो <1000 * 1000 प्रशिक्षण चित्र * Iterations है।
लिंडन व्हाइट

आप सही हैं, मैं उस मुद्दे को ठीक कर दूंगा। मेरे कोड के साथ एक और भी अधिक महत्वपूर्ण समस्या है: मैं लॉजिस्टिक न्यूरॉन्स का उपयोग कर रहा हूं जो कि (कॉस, पाप) प्रतिनिधित्व द्वारा आवश्यक नकारात्मक मूल्यों का उत्पादन करने में असमर्थ हैं। डी 'ओह! मैं अपने कोड को संशोधित कर जल्द से जल्द पोस्ट करूंगा।
ऐरी हरमन

आप कर सकते हैं (यदि आपने पहले से ऐसा नहीं किया है) एक ग्रैडिड चेक करने में रुचि रखते हैं , जो खरोंच से तंत्रिका नेटवर्क को लागू करने के लिए सार्थक है, क्योंकि यह एक छोटी सी गलती करना बहुत आसान है और आपके नेटवर्क में अभी भी ज्यादातर काम है। रे: न्यूरॉन: हाँ, मेरे पास एक लीनियर आउटपुट लेयर है, सिग्मोइड हिडन लेयर पर
Lyndon White

1

कोण को एन्कोड करने का एक और तरीका दो मानों का एक सेट है:

y1 = अधिकतम (0, थीटा)

y2 = max (0, -थे)

थीटा_आउट = y1 - y2

यह arctan2 के लिए समान समस्या होगी कि ग्रेडिएंट theta = पर अपरिभाषित है। 0. मेरे पास एक नेटवर्क को प्रशिक्षित करने और अन्य एन्कोडिंग की तुलना करने का समय नहीं है, लेकिन इस पत्र में तकनीक काफी सफल लग रही थी।


1
यह एक पोस्ट में एक और प्रश्न के साथ मिश्रित उत्तर की तरह लगता है। यह साइट जिस तरह से फोरम करेगी उससे थोड़ा अलग तरीके से काम करती है। यहां मूल प्रश्न का उत्तर देने पर ध्यान केंद्रित करना चाहिए। और अगर आपके पास एक और सवाल या एक टिप्पणी है - इसे इस तरह से पोस्ट किया जाना चाहिए।
करोलिस कोनसीविअस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.