Python 3.x 随机梯度下降到底是怎么回事

Python 3.x 随机梯度下降到底是怎么回事,python-3.x,machine-learning,linear-regression,gradient-descent,Python 3.x,Machine Learning,Linear Regression,Gradient Descent,我正在使用多元线性回归,并使用随机梯度下降优化 处理此数据集 对于每次运行,所有超参数和所有剩余内容都是相同的,epochs=200,alpha=0.1 当我第一次运行时,我得到final_cost=0.0591,当我再次运行程序时,保持一切不变,我得到final_cost=1.0056 ,再次运行,保持一切不变,我得到最终成本=0.8214 ,再次运行最终成本=15.9591,再次运行最终成本=2.3162,依此类推 正如你所看到的,保持一切不变并运行,一次又一次,每次最终成本变化很大,有时

我正在使用多元线性回归,并使用随机梯度下降优化

处理此数据集

对于每次运行,所有超参数和所有剩余内容都是相同的,epochs=200,alpha=0.1

当我第一次运行时,我得到final_cost=0.0591,当我再次运行程序时,保持一切不变,我得到final_cost=1.0056 ,再次运行,保持一切不变,我得到最终成本=0.8214 ,再次运行最终成本=15.9591,再次运行最终成本=2.3162,依此类推

正如你所看到的,保持一切不变并运行,一次又一次,每次最终成本变化很大,有时从0.8变为直接15.9,0.05到直接1.00,不仅如此,同一运行中每个历元后的最终成本图是每个锯齿形的,不像批次GD中的成本图平稳下降

我不明白为什么SGD的行为如此怪异,在不同的运行中会产生不同的结果

我尝试了同样的批GD和一切都是绝对的罚款和顺利按照预期。在批处理GD的情况下,无论我运行同一代码多少次,每次的结果都是完全相同的

但就SGD而言,我真的哭了

class Abalone : 
    def __init__(self,df,epochs=200,miniBatchSize=250,alpha=0.1) :

        self.df = df.dropna()
        self.epochs = epochs
        self.miniBatchSize = miniBatchSize
        self.alpha = alpha

        print("abalone created")
        self.modelTheData()


    def modelTheData(self) :

        self.TOTAL_ATTR = len(self.df.columns) - 1
        self.TOTAL_DATA_LENGTH = len(self.df.index)

        self.df_trainingData = 
        df.drop(df.index[int(self.TOTAL_DATA_LENGTH * 0.6):])

        self.TRAINING_DATA_SIZE = len(self.df_trainingData)

        self.df_testingData = 
        df.drop(df.index[:int(self.TOTAL_DATA_LENGTH * 0.6)])

        self.TESTING_DATA_SIZE = len(self.df_testingData)

        self.miniBatchSize = int(self.TRAINING_DATA_SIZE / 10)

        self.thetaVect = np.zeros((self.TOTAL_ATTR+1,1),dtype=float)

        self.stochasticGradientDescent()


    def stochasticGradientDescent(self) :

        self.finalCostArr = np.array([])

        startTime = time.time()    

        for i in range(self.epochs) :

            self.df_trainingData = 
            self.df_trainingData.sample(frac=1).reset_index(drop=True)

            miniBatches=[self.df_trainingData.loc[x:x+self.miniBatchSize-
                  ((x+self.miniBatchSize)/(self.TRAINING_DATA_SIZE-1)),:]
            for x in range(0,self.TRAINING_DATA_SIZE,self.miniBatchSize)]          

            self.epochCostArr = np.array([])

            for j in miniBatches : 

                tempMat = j.values
                self.actualValVect = tempMat[ : , self.TOTAL_ATTR:]
                tempMat = tempMat[ : , :self.TOTAL_ATTR]
                self.desMat = np.append( 
                np.ones((len(j.index),1),dtype=float) , tempMat , 1 )                
                del tempMat

                self.trainData()

                currCost = self.costEvaluation()
                self.epochCostArr = np.append(self.epochCostArr,currCost)

            self.finalCostArr = np.append(self.finalCostArr,
                                   self.epochCostArr[len(miniBatches)-1])

        endTime = time.time()
        print(f"execution time : {endTime-startTime}")
        self.graphEvaluation()
        print(f"final cost : 
                {self.finalCostArr[len(self.finalCostArr)-1]}")
        print(self.thetaVect)


    def trainData(self) :

        self.predictedValVect = self.predictResult()
        diffVect = self.predictedValVect - self.actualValVect
        partialDerivativeVect = np.matmul(self.desMat.T , diffVect)
        self.thetaVect -= 
                      (self.alpha/len(self.desMat))*partialDerivativeVect


    def predictResult(self) :

        return np.matmul(self.desMat,self.thetaVect)


    def costEvaluation(self) : 

        cost =  sum((self.predictedValVect - self.actualValVect)**2)
        return cost / (2*len(self.actualValVect))


    def graphEvaluation(self) : 

        plt.title("cost at end of all epochs")
        x = range(len(self.epochCostArr))
        y = self.epochCostArr
        plt.plot(x,y)
        plt.xlabel("iterations")
        plt.ylabel("cost")
        plt.show()
我在所有的跑步中都保持epochs=200和alpha=0.1,但每次跑步的结果都完全不同

下面提到的向量是θ向量,其中第一个条目是偏差,其余的是权重

RUN 1 =>>

[[  5.26020144]
[ -0.48787333]
[  4.36479114]
[  4.56848299]
[  2.90299436]
[  3.85349625]
[-10.61906207]
[ -0.93178027]
[  8.79943389]]

final cost : 0.05917831328836957


RUN 2 =>>

[[  5.18355814]
[ -0.56072668]
[  4.32621647]
[  4.58803884]
[  2.89157598]
[  3.7465471 ]
[-10.75751065]
[ -1.03302031]
[  8.87559247]]

final cost: 1.0056239103948563


RUN 3 =>>

[[  5.12836056]
[ -0.43672936]
[  4.25664898]
[  4.53397465]
[  2.87847224]
[  3.74693215]
[-10.73960775]
[ -1.00461585]
[  8.85225402]]

final cost : 0.8214901206702101


RUN 4 =>>

[[  5.38794798]
[  0.23695412]
[  4.43522951]
[  4.66093372]
[  2.9460605 ]
[  4.13390252]
[-10.60071883]
[ -0.9230675 ]
[  8.87229324]]

final cost: 15.959132174895712


RUN 5 =>>

[[  5.19643132]
[ -0.76882106]
[  4.35445135]
[  4.58782119]
[  2.8908931 ]
[  3.63693031]
[-10.83291949]
[ -1.05709616]
[  8.865904  ]]

final cost: 2.3162151072779804
我不知道出了什么问题。SGD的行为是这样的还是我在将代码从批处理GD转换为SGD时做了一些愚蠢的事情。如果SGD的行为是这样的,那么我如何知道我必须重新运行多少次,因为我不是很幸运,每次在第一次运行时,我得到的成本都很小,比如0.05,有时第一次运行的成本约为10.5,有时为0.6,也许重新运行很多次,我得到的成本甚至小于0.05

当我用完全相同的代码和超参数处理完全相同的问题时,仅仅用正常的批处理GD替换SGD函数,我得到了预期的结果,即,在对相同数据进行每次迭代后,我的成本平稳地降低,即。,一个单调递减函数,无论我重新运行同一个程序多少次,我都得到了完全相同的结果,因为这是非常明显的

“保持一切不变,但对EPOCH=20000和alpha=0.1使用批处理GD 我得到了最终成本=2.7474“


谁来帮我弄清楚到底发生了什么。在这个新领域,每一个意见/解决方案对我来说都是一笔巨大的收入:)

你错过了GD(“梯度下降”)和SGD(“随机梯度下降”)之间最重要也是唯一的区别

随机性——字面意思是“缺乏任何可预测的顺序或计划的性质”。意思是随机性

这意味着,在GD算法中,每个历元中样本的顺序保持不变,而在SGD中,顺序在每个历元开始时随机洗牌。 因此,每次使用相同的初始化和超参数运行GD都会产生完全相同的结果,而SGD显然不会(正如您所经历的那样)

使用随机性的原因是为了防止模型记住训练样本(这将导致过度拟合,训练集的准确度将很高,但看不见样本的准确度将很差)


现在,关于你的案例中两次跑步的最终成本值的巨大差异,我猜你的学习率太高了。你可以使用一个较低的常量值,或者更好的是,使用一个衰减的学习率(随着时间的推移,学习率会越来越低)。

我尝试了几乎所有的方法,但没有明显的变化,我仍然获得了一些巨大的跳跃。我的代码正确吗?是的,很好。
def BatchGradientDescent(self) :

    self.costArr = np.array([])

    startTime = time.time()

    for i in range(self.epochs) :

            tempMat = self.df_trainingData.values
            self.actualValVect = tempMat[ : , self.TOTAL_ATTR:]
            tempMat = tempMat[ : , :self.TOTAL_ATTR]
            self.desMat = np.append( np.ones((self.TRAINING_DATA_SIZE,1),dtype=float) , tempMat , 1 )                
            del tempMat

            self.trainData()

            if i%100 == 0 :

                currCost = self.costEvaluation()
                self.costArr = np.append(self.costArr,currCost)

    endTime = time.time()

    print(f"execution time : {endTime - startTime} seconds")
    self.graphEvaluation()
    print(self.thetaVect)
    print(f"final cost : {self.costArr[len(self.costArr)-1]}")