গ্রেডিয়েন্ট বংশোদ্ভূত এই ডেটাসেটের সাধারণ ন্যূনতম স্কোয়ারগুলির সমাধান খুঁজে পাচ্ছেন না?


12

আমি লিনিয়ার রিগ্রেশন অধ্যয়ন করছি এবং নীচে সেট on (x, y) tried এ চেষ্টা করে দেখছি, যেখানে x বর্গফুটে বাড়ির ক্ষেত্রফল নির্দিষ্ট করেছে এবং y ডলারে মূল্য নির্দিষ্ট করেছে। এটি অ্যান্ড্রু এনজি নোটসের প্রথম উদাহরণ ।

2104.400
1600.330
2400.369
1416.232
3000.540

আমি একটি নমুনা কোড বিকাশ করেছি কিন্তু আমি যখন এটি চালাচ্ছি তখন প্রতিটি পদক্ষেপের সাথে ব্যয় বাড়ছে যেখানে প্রতিটি পদক্ষেপের সাথে এটি হ্রাস হওয়া উচিত। কোড এবং আউটপুট নীচে দেওয়া হয়েছে। biasডাব্লু 0 এক্স 0 , যেখানে এক্স 0 = 1। featureWeights[এক্স 1 , এক্স 2 , ..., এক্স এন ] এর একটি অ্যারে

আমিও একটি অনলাইন পাইথন সমাধান চেষ্টা প্রাপ্তিসাধ্য এখানে , এবং এখানে ব্যাখ্যা । তবে এই উদাহরণটিও একই আউটপুট দিচ্ছে।

ধারণাটি বোঝার ফাঁক কোথায়?

কোড:

package com.practice.cnn;

import java.util.Arrays;

public class LinearRegressionExample {

    private float ALPHA = 0.0001f;
    private int featureCount = 0;
    private int rowCount = 0;

    private float bias = 1.0f;
    private float[] featureWeights = null;

    private float optimumCost = Float.MAX_VALUE;

    private boolean status = true;

    private float trainingInput[][] = null;
    private float trainingOutput[] = null;

    public void train(float[][] input, float[] output) {
        if (input == null || output == null) {
            return;
        }

        if (input.length != output.length) {
            return;
        }

        if (input.length == 0) {
            return;
        }

        rowCount = input.length;
        featureCount = input[0].length;

        for (int i = 1; i < rowCount; i++) {
            if (input[i] == null) {
                return;
            }

            if (featureCount != input[i].length) {
                return;
            }
        }

        featureWeights = new float[featureCount];
        Arrays.fill(featureWeights, 1.0f);

        bias = 0;   //temp-update-1
        featureWeights[0] = 0;  //temp-update-1

        this.trainingInput = input;
        this.trainingOutput = output;

        int count = 0;
        while (true) {
            float cost = getCost();

            System.out.print("Iteration[" + (count++) + "] ==> ");
            System.out.print("bias -> " + bias);
            for (int i = 0; i < featureCount; i++) {
                System.out.print(", featureWeights[" + i + "] -> " + featureWeights[i]);
            }
            System.out.print(", cost -> " + cost);
            System.out.println();

//          if (cost > optimumCost) {
//              status = false;
//              break;
//          } else {
//              optimumCost = cost;
//          }

            optimumCost = cost;

            float newBias = bias + (ALPHA * getGradientDescent(-1));

            float[] newFeaturesWeights = new float[featureCount];
            for (int i = 0; i < featureCount; i++) {
                newFeaturesWeights[i] = featureWeights[i] + (ALPHA * getGradientDescent(i));
            }

            bias = newBias;

            for (int i = 0; i < featureCount; i++) {
                featureWeights[i] = newFeaturesWeights[i];
            }
        }
    }

    private float getCost() {
        float sum = 0;
        for (int i = 0; i < rowCount; i++) {
            float temp = bias;
            for (int j = 0; j < featureCount; j++) {
                temp += featureWeights[j] * trainingInput[i][j];
            }

            float x = (temp - trainingOutput[i]) * (temp - trainingOutput[i]);
            sum += x;
        }
        return (sum / rowCount);
    }

    private float getGradientDescent(final int index) {
        float sum = 0;
        for (int i = 0; i < rowCount; i++) {
            float temp = bias;
            for (int j = 0; j < featureCount; j++) {
                temp += featureWeights[j] * trainingInput[i][j];
            }

            float x = trainingOutput[i] - (temp);
            sum += (index == -1) ? x : (x * trainingInput[i][index]);
        }
        return ((sum * 2) / rowCount);
    }

    public static void main(String[] args) {
        float[][] input = new float[][] { { 2104 }, { 1600 }, { 2400 }, { 1416 }, { 3000 } };

        float[] output = new float[] { 400, 330, 369, 232, 540 };

        LinearRegressionExample example = new LinearRegressionExample();
        example.train(input, output);
    }
}

আউটপুট:

Iteration[0] ==> bias -> 0.0, featureWeights[0] -> 0.0, cost -> 150097.0
Iteration[1] ==> bias -> 0.07484, featureWeights[0] -> 168.14847, cost -> 1.34029099E11
Iteration[2] ==> bias -> -70.60721, featureWeights[0] -> -159417.34, cost -> 1.20725801E17
Iteration[3] ==> bias -> 67012.305, featureWeights[0] -> 1.51299168E8, cost -> 1.0874295E23
Iteration[4] ==> bias -> -6.3599688E7, featureWeights[0] -> -1.43594258E11, cost -> 9.794949E28
Iteration[5] ==> bias -> 6.036088E10, featureWeights[0] -> 1.36281745E14, cost -> 8.822738E34
Iteration[6] ==> bias -> -5.7287012E13, featureWeights[0] -> -1.29341617E17, cost -> Infinity
Iteration[7] ==> bias -> 5.4369677E16, featureWeights[0] -> 1.2275491E20, cost -> Infinity
Iteration[8] ==> bias -> -5.1600908E19, featureWeights[0] -> -1.1650362E23, cost -> Infinity
Iteration[9] ==> bias -> 4.897313E22, featureWeights[0] -> 1.1057068E26, cost -> Infinity
Iteration[10] ==> bias -> -4.6479177E25, featureWeights[0] -> -1.0493987E29, cost -> Infinity
Iteration[11] ==> bias -> 4.411223E28, featureWeights[0] -> 9.959581E31, cost -> Infinity
Iteration[12] ==> bias -> -4.186581E31, featureWeights[0] -> -Infinity, cost -> Infinity
Iteration[13] ==> bias -> Infinity, featureWeights[0] -> NaN, cost -> NaN
Iteration[14] ==> bias -> NaN, featureWeights[0] -> NaN, cost -> NaN

এটি এখানে বিষয় বন্ধ।
মাইকেল আর। চেরনিক

3
জিনিসগুলি এখানে যেমন হয় তেমন অসীম দিকে উড়ে যায়, আপনি সম্ভবত ভেক্টরের স্কেল দিয়ে কোথাও বিভাজন করতে ভুলে যাচ্ছেন।
স্টাসকে

5
ম্যাথু দ্বারা গৃহীত উত্তর স্পষ্টতই পরিসংখ্যানগত। এর অর্থ হল যে প্রশ্নের উত্তর দেওয়ার জন্য স্ট্যাটিস্টিকাল (এবং প্রোগ্রামিং নয়) দক্ষতার প্রয়োজন; এটি সংজ্ঞা অনুসারে বিষয়কে এটি করে তোলে। আমি আবার খুলতে ভোট।
অ্যামিবা বলেছেন

উত্তর:


35

সংক্ষিপ্ত উত্তরটি হ'ল আপনার পদক্ষেপের আকারটি অনেক বড়। পরিবর্তে গভীর খাদ প্রাচীর সাজানো, আপনার পদক্ষেপ এত বড় যে তুমি এক দিক থেকে জুড়ে জাম্পিং উচ্চতর অন্যদিকে আপ!

নীচে ব্যয় কার্য:

এখানে চিত্র বর্ণনা লিখুন

দীর্ঘ উত্তর হ'ল এই সমস্যাটি সমাধান করা নিরীহ গ্রেডিয়েন্ট বংশোদ্ভূতদের পক্ষে কারণ আপনার ব্যয় ক্রিয়াকলাপের স্তর সেটগুলি বৃত্তের চেয়ে উচ্চ বর্ধিত উপবৃত্তাকার। এই সমস্যাটিকে দৃust়তার সাথে সমাধান করার জন্য নোট করুন যে আরও কয়েকটি অত্যাধুনিক উপায় বেছে নেওয়ার জন্য রয়েছে:

  • একটি ধাপের আকার (ধ্রুবককে হার্ডকডিংয়ের চেয়ে)
  • একটি পদক্ষেপের দিক (গ্রেডিয়েন্ট বংশদ্ভুতের চেয়ে)

অন্তর্নিহিত সমস্যা

অন্তর্নিহিত সমস্যাটি হ'ল আপনার ব্যয় ফাংশনের স্তরের সেটগুলি অত্যন্ত বর্ধিত উপবৃত্তাকার এবং এটি গ্রেডিয়েন্ট বংশোদ্ভূত সমস্যার জন্য সমস্যা তৈরি করে। নীচের চিত্রটি ব্যয় ফাংশনের জন্য স্তর সেটগুলি দেখায়।

  • 026.789
  • যদি পদক্ষেপের আকারটি খুব বড় হয় তবে আপনি আক্ষরিকভাবে নীচের নীচের অঞ্চলে ঝাঁপিয়ে পড়বেন এবং নামার পরিবর্তে আরোহণ করবেন।
  • θ0

আমি এই উত্তরটি কোয়ারায় পড়ার পরামর্শ দিচ্ছি ।

এখানে চিত্র বর্ণনা লিখুন

দ্রুত ফিক্স 1:

আপনার কোডটি এতে পরিবর্তন করুন private float ALPHA = 0.0000002f;এবং আপনি ওভারশুটিং বন্ধ করবেন।

দ্রুত ফিক্স 2:

XX

আরও উন্নত সংশোধন

যদি লক্ষ্যটি দক্ষতার সাথে কোনও শ্রেণীর জন্য গ্রেডিয়েন্ট বংশোদ্ভূত না শেখার পরিবর্তে দক্ষতার সাথে কমপক্ষে স্কোয়ারগুলি সমাধান করা হত তবে তা লক্ষ্য করুন:

  • লাইন অনুসন্ধান এবং আর্মিজো নিয়মের মতো পদক্ষেপের আকার গণনা করার আরও সূক্ষ্ম উপায় রয়েছে ।
  • একটি উত্তরের নিকটে যেখানে স্থানীয় অবস্থার প্রাধান্য রয়েছে, নিউটনের পদ্ধতিটি চতুর্ভুজীয় একত্রিতকরণ লাভ করে এবং একটি ধাপের দিক এবং আকার চয়ন করার দুর্দান্ত উপায়।
  • সর্বনিম্ন স্কোয়ারগুলি সমাধান করা লিনিয়ার সিস্টেমটি সমাধানের সমতুল্য। আধুনিক অ্যালগরিদমগুলি নিষ্পাপ গ্রেডিয়েন্ট বংশদ্ভুত ব্যবহার করে না। পরিবর্তে:
    • k
    • বড় সিস্টেমে তারা এটিকে একটি অপ্টিমাইজেশনের সমস্যা হিসাবে চিহ্নিত করে এবং পুনরাবৃত্ত পদ্ধতিগুলি যেমন ক্রেলোভ সাবস্পেস পদ্ধতি ব্যবহার করে।

(XX)b=Xyb

আসল সমাধানটি হ'ল

  26.789880528523071
   0.165118878075797

আপনি দেখতে পাবেন যেগুলি ব্যয় কার্যের জন্য ন্যূনতম মান অর্জন করে।


5
+1 অন্যান্য ব্যক্তিকে কোড ডিবাগ করতে দেওয়া বিলাসিতা!
হাইতাও ডু

4
@ hxd1011 আমি ভেবেছিলাম এটি প্রথমে বোবা কোডিং ত্রুটি ছিল, তবে পরিবর্তে এটি (ইমো) পরিণত হবে যা নিখুঁত গ্রেডিয়েন্ট বংশোদ্ভূত হওয়ার সাথে কী ভুল হতে পারে তার একটি যথেষ্ট শিক্ষামূলক উদাহরণ হতে পারে।
ম্যাথু গন

@ ম্যাথেজগান আমি সমাধান পেয়েছি b = 0.99970686, m = 0.17655967 (y = mx + b)। এবং "ধ্রুবককে হার্ডকডিংয়ের চেয়ে একটি ধাপের আকার" বলতে কী বোঝায়? তার মানে কি আমাদের প্রতিটি পুনরাবৃত্তির জন্য এটি পরিবর্তন করা উচিত? অথবা আমাদের ইনপুট মানগুলির উপর ভিত্তি করে এটি গণনা করতে হবে?
আম্বর বেরিওয়াল

αiiααif

অ্যাম্বেরবেরিওয়াল আপনি পাবেন যে (26.789, .1651) এর দাম কিছুটা কম হবে। এটি (.9997, .1766) থেকে কিছুটা উতরাইয়ের দিকে যেখানে ব্যয়টির কার্যকারিতাটি একটি ছোট opeালু।
ম্যাথু গুন

2

যেমন ম্যাথু (গন) ইতিমধ্যে ইঙ্গিত করেছেন, ত্রি-মাত্রিক ব্যয় বা পারফরম্যান্স ফাংশনটির রূপগুলি এই ক্ষেত্রে অত্যন্ত উপবৃত্তাকার। যেহেতু আপনার জাভা কোড গ্রেডিয়েন্ট বংশদ্ভুত গণনার জন্য একক পদক্ষেপ-আকারের মান ব্যবহার করে, তাই ওজনের আপডেটগুলি (অর্থাত্ y- অক্ষ ইন্টারসেপ্ট এবং লিনিয়ার ফাংশনের opeালু) উভয়ই এই একক পদক্ষেপ-আকার দ্বারা পরিচালিত হয়।

ফলস্বরূপ, বৃহত্তর গ্রেডিয়েন্টের সাথে যুক্ত ওজনের হালনাগাদ নিয়ন্ত্রণের জন্য খুব ছোট পদক্ষেপের আকারের প্রয়োজন হয় (এই ক্ষেত্রে, লিনিয়ার ফাংশনের opeাল) ছোট ভার্ডিয়েন্টের সাথে অন্যান্য ওজনকে কত দ্রুত দ্রুত সীমাবদ্ধ করে ( লিনিয়ার ফাংশনের y- অক্ষ ইন্টারসেপ্ট) আপডেট করা হয়েছে। বর্তমান অবস্থার অধীনে, পরবর্তী ওজন এটির প্রায় 26.7 এর সত্যিকার মানে রূপান্তর করে না।

আপনি আপনার জাভা কোডটি লেখার জন্য যে সময় এবং প্রচেষ্টা ব্যয় করেছেন তা বিবেচনা করে আমি আপনাকে দুটি ধাপে ধাপে-আকারের মানগুলি ব্যবহার করার জন্য এটি পরিবর্তন করার পরামর্শ দেব, প্রতিটি ওজনের জন্য উপযুক্ত পদক্ষেপের আকার। অ্যান্ড্রু এনজি তার নোটগুলিতে পরামর্শ দিয়েছেন যে ব্যয় ক্রিয়াকলাপগুলি আরও নিয়মিত (যেমন বিজ্ঞপ্তি) আকারে রয়েছে তা নিশ্চিত করার জন্য বৈশিষ্ট্য স্কেলিং ব্যবহার করা ভাল। তবে প্রতিটি ওজনের জন্য আলাদা পদক্ষেপ-আকার ব্যবহার করতে আপনার জাভা কোডটি সংশোধন করা বৈশিষ্ট্য স্কেলিংয়ের পাশাপাশি দেখার জন্য একটি ভাল অনুশীলনও হতে পারে।

বিবেচনা করার জন্য আরেকটি ধারণা হ'ল প্রাথমিক ওজনের মানগুলি কীভাবে বাছাই করা হয়। আপনার জাভা কোডে আপনি উভয় মান শূন্যে শুরু করেছেন। ওজনকে ছোট, ভগ্নাংশের মান থেকে আরম্ভ করার পক্ষেও খুব সাধারণ বিষয়। এই বিশেষ ক্ষেত্রে, তবে, এই উভয় পন্থা ত্রিমাত্রিক ব্যয় ফাংশনের অত্যন্ত উপবৃত্তাকার (অর্থাত্কৃত-বৃত্তাকার) সংশ্লেষের আলোতে কাজ করবে না। এই পোস্টের শেষে ম্যাথিউর দ্বারা প্রস্তাবিত রৈখিক পদ্ধতির সমাধানের মতো অন্যান্য পদ্ধতির সাহায্যে এই সমস্যার জন্য ওজন পাওয়া যায়, আপনি সঠিক ওজনের নিকটতম মানগুলির ওজনকে আরম্ভ করার চেষ্টা করতে পারেন এবং কীভাবে আপনার মূল কোডটি দেখুন একক পদক্ষেপ-আকারের রূপান্তর ব্যবহার করে।

পাইথন কোডটি আপনি খুঁজে পেয়েছেন সমাধানটি আপনার জাভা কোডের মতো একইভাবে - উভয়ই একক পদক্ষেপ-আকারের প্যারামিটার ব্যবহার করে। আমি এই পাইথন কোডটি প্রতিটি ওজনের জন্য আলাদা ধাপ-আকার ব্যবহার করতে সংশোধন করেছি। আমি এটি নীচে অন্তর্ভুক্ত করেছি।

from numpy import *

def compute_error_for_line_given_points(b, m, points):
    totalError = 0
    for i in range(0, len(points)):
        x = points[i, 0]
        y = points[i, 1]
        totalError += (y - (m * x + b)) ** 2
    return totalError / float(len(points))

def step_gradient(b_current, m_current, points, learningRate_1, learningRate_2):
    b_gradient = 0
    m_gradient = 0
    N = float(len(points))
    for i in range(0, len(points)):
        x = points[i, 0]
        y = points[i, 1]
        b_gradient += -(2/N) * (y - ((m_current * x) + b_current))
        m_gradient += -(2/N) * x * (y - ((m_current * x) + b_current))
    new_b = b_current - (learningRate_1 * b_gradient)
    new_m = m_current - (learningRate_2 * m_gradient)
    return [new_b, new_m]

def gradient_descent_runner(points, starting_b, starting_m, learning_rate_1, learning_rate_2, num_iterations):
    b = starting_b
    m = starting_m
    for i in range(num_iterations):
        b, m = step_gradient(b, m, array(points), learning_rate_1, learning_rate_2)
    return [b, m]

def run():
    #points = genfromtxt("data.csv", delimiter=",")
    #learning_rate = 0.0001
    #num_iterations = 200

    points = genfromtxt("test_set.csv", delimiter=",")
    learning_rate_1 = 0.5
    learning_rate_2 = 0.0000001
    num_iterations = 1000

    initial_b = 0 # initial y-intercept guess
    initial_m = 0 # initial slope guess


    print("Starting gradient descent at b = {0}, m = {1}, error = {2}".format(initial_b, initial_m, compute_error_for_line_given_points(initial_b, initial_m, points)))
    print("Running...")

    [b, m] = gradient_descent_runner(points, initial_b, initial_m, learning_rate_1, learning_rate_2, num_iterations)

    print("After {0} iterations b = {1}, m = {2}, error = {3}".format(num_iterations, b, m, compute_error_for_line_given_points(b, m, points)))

if __name__ == '__main__':
    run()

এটি পাইথন 3 এর অধীনে চলে, যার জন্য "মুদ্রণ" বিবৃতিগুলির পক্ষে যুক্তির আশেপাশে প্রথম বন্ধনী প্রয়োজন requires অন্যথায় এটি প্রথম বন্ধনীগুলি সরিয়ে পাইথন 2 এর অধীনে চলবে। অ্যান্ড্রু এনজির উদাহরণ থেকে আপনার ডেটা সহ একটি সিএসভি-ফাইল তৈরি করতে হবে।

আপনার জাভা কোডটি পরীক্ষা করতে পাইথন কোডটি ব্যবহার করে ক্রস-রেফারেন্স করতে পারে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.