模型训练 准确率下降_手写批量线性回归算法:在Python3中梯度下降方法实现模型训练
在這篇文章中,我們將看一個使用NumPy作為數據處理庫的Python3編寫的程序,來了解如何實現使用梯度下降法的(批量)線性回歸。
? 我將逐步解釋代碼的工作原理和代碼的每個部分的工作原理。
? 我們將使用此公式計算梯度。
? 在此,x(i)向量是一個點,其中N是數據集的大小。 n(eta)是我們的學習率。 y(i)向量是目標輸出。 f(x)向量是定義為f(x)= Sum(w * x)的回歸線性函數,這里sum是sigma函數。 另外,我們將考慮初始偏差w0 = 0并使得x0 =1。所有權重均初始化為0。
? 在此方法中,我們將平方誤差總和用作損失函數。
? 除了將SSE初始化為零外,我們將在每次迭代中記錄SSE的變化,并將其與在程序執行之前提供的閾值進行比較。 如果SSE低于閾值,程序將退出。
? 在該程序中,我們從命令行提供了三個輸入。 他們是:
threshold — 閾值,在算法終止之前,損失必須低于此閾值。
data — 數據集的位置。
learningRate — 梯度下降法的學習率。
? 因此,該程序的啟動應該是這樣的:
python3linearregr.py — datarandom.csv — learningRate 0.0001 — threshold 0.0001? 在深入研究代碼之前我們確定最后一件事,程序的輸出將如下所示:
iteration_number,weight0,weight1,weight2,...,weightN,sum_of_squared_errors? 該程序包括6個部分,我們逐個進行查看。
導入模塊
import argparse # to read inputs from command lineimport csv # to read the input data set fileimport numpy as np # to work with the data set初始化部分
# initialise argument parser and read argumentsfrom command line with the respective flags and then call the main() functionif __name__ == '__main__': parser = argparse.ArgumentParser()parser.add_argument("-d", "--data", help="Data File")parser.add_argument("-l", "--learningRate", help="Learning Rate") parser.add_argument("-t", "--threshold", help="Threshold") main()main函數部分
defmain():args = parser.parse_args()file, learningRate, threshold = args.data, float(args.learningRate), float(args.threshold) # save respective command line inputs into variables# read csv file and the last column is the target output and is separated from the input (X) as Ywith open(file) as csvFile:reader = csv.reader(csvFile, delimiter=',')X = []Y = []for row in reader:X.append([1.0] + row[:-1])Y.append([row[-1]])# Convert data points into float and initialise weight vector with 0s.n = len(X)X = np.array(X).astype(float)Y = np.array(Y).astype(float)W = np.zeros(X.shape[1]).astype(float)# this matrix is transposed to match the necessary matrix dimensions for calculating dot productW = W.reshape(X.shape[1], 1).round(4)# Calculate the predicted output valuef_x = calculatePredicatedValue(X, W)# Calculate the initial SSEsse_old = calculateSSE(Y, f_x)outputFile = 'solution_' + 'learningRate_' + str(learningRate) + '_threshold_' + str(threshold) + '.csv''''Output file is opened in writing mode and the data is written in the format mentioned in the post. After thefirst values are written, the gradient and updated weights are calculated using the calculateGradient function.An iteration variable is maintained to keep track on the number of times the batch linear regression is executedbefore it falls below the threshold value. In the infinite while loop, the predicted output value is calculated again and new SSE value is calculated. If the absolute difference between the older(SSE from previous iteration) and newer(SSE from current iteration) SSE is greater than the threshold value, then above process is repeated.The iteration is incremented by 1 and the current SSE is stored into previous SSE. If the absolute difference between the older(SSE from previous iteration) and newer(SSE from current iteration) SSE falls below the threshold value, the loop breaks and the last output values are written to the file.'''with open(outputFile, 'w', newline='') as csvFile:writer = csv.writer(csvFile, delimiter=',', quoting=csv.QUOTE_NONE, escapechar='')writer.writerow([*[0], *["{0:.4f}".format(val) for val in W.T[0]], *["{0:.4f}".format(sse_old)]])gradient, W = calculateGradient(W, X, Y, f_x, learningRate)iteration = 1whileTrue:f_x = calculatePredicatedValue(X, W)sse_new = calculateSSE(Y, f_x)if abs(sse_new - sse_old) > threshold:writer.writerow([*[iteration], *["{0:.4f}".format(val) for val in W.T[0]], *["{0:.4f}".format(sse_new)]])gradient, W = calculateGradient(W, X, Y, f_x, learningRate)iteration += 1sse_old = sse_newelse:breakwriter.writerow([*[iteration], *["{0:.4f}".format(val) for val in W.T[0]], *["{0:.4f}".format(sse_new)]])print("Output File Name: " + outputFile? main函數的流程如下所示:
calculatePredicatedValue函數
? 在此,通過執行輸入矩陣X和權重矩陣W的點積來計算預測輸出。
# dot product of X(input) and W(weights) as numpy matrices and returning the result which is the predicted outputdefcalculatePredicatedValue(X, W):f_x = np.dot(X, W)return f_xcalculateGradient函數
? 使用文章中提到的第一個公式計算梯度并更新權重。
defcalculateGradient(W, X, Y, f_x, learningRate):gradient = (Y - f_x) * Xgradient = np.sum(gradient, axis=0)temp = np.array(learningRate * gradient).reshape(W.shape)W = W + tempreturn gradient, WcalculateSSE函數
? 使用上述公式計算SSE。
defcalculateSSE(Y, f_x): sse = np.sum(np.square(f_x - Y)) return sse? 現在,看完了完整的代碼。 讓我們看一下程序的執行結果。
? 這是輸出的樣子:00.00000.00000.00007475.31491-0.0940-0.5376-0.25922111.51052-0.1789-0.7849-0.3766880.69803-0.2555-0.8988-0.4296538.86384-0.3245-0.9514-0.4533399.80925-0.3867-0.9758-0.4637316.16826-0.4426-0.9872-0.4682254.51267-0.4930-0.9926-0.4699205.84798-0.5383-0.9952-0.4704166.69329-0.5791-0.9966-0.4704135.029310-0.6158-0.9973-0.4702109.389211-0.6489-0.9978-0.470088.619712-0.6786-0.9981-0.469771.794113-0.7054-0.9983-0.469458.163114-0.7295-0.9985-0.469147.120115-0.7512-0.9987-0.468938.173816-0.7708-0.9988-0.468730.926117-0.7883-0.9989-0.468525.054418-0.8042-0.9990-0.468320.297519-0.8184-0.9991-0.468116.443820-0.8312-0.9992-0.468013.321821-0.8427-0.9993-0.467810.792522-0.8531-0.9994-0.46778.743423-0.8625-0.9994-0.46767.083324-0.8709-0.9995-0.46755.738525-0.8785-0.9995-0.46744.649026-0.8853-0.9996-0.46743.766327-0.8914-0.9996-0.46733.051228-0.8969-0.9997-0.46722.471929-0.9019-0.9997-0.46722.002630-0.9064-0.9997-0.46711.622431-0.9104-0.9998-0.46711.314432-0.9140-0.9998-0.46701.064833-0.9173-0.9998-0.46700.862634-0.9202-0.9998-0.46700.698935-0.9229-0.9998-0.46690.566236-0.9252-0.9999-0.46690.458737-0.9274-0.9999-0.46690.371638-0.9293-0.9999-0.46690.301039-0.9310-0.9999-0.46680.243940-0.9326-0.9999-0.46680.197641-0.9340-0.9999-0.46680.160142-0.9353-0.9999-0.46680.129743-0.9364-0.9999-0.46680.105144-0.9374-0.9999-0.46680.085145-0.9384-0.9999-0.46680.069046-0.9392-0.9999-0.46680.055947-0.9399-1.0000-0.46670.045348-0.9406-1.0000-0.46670.036749-0.9412-1.0000-0.46670.029750-0.9418-1.0000-0.46670.024151-0.9423-1.0000-0.46670.019552-0.9427-1.0000-0.46670.015853-0.9431-1.0000-0.46670.012854-0.9434-1.0000-0.46670.010455-0.9438-1.0000-0.46670.008456-0.9441-1.0000-0.46670.006857-0.9443-1.0000-0.46670.005558-0.9446-1.0000-0.46670.004559-0.9448-1.0000-0.46670.003660-0.9450-1.0000-0.46670.002961-0.9451-1.0000-0.46670.002462-0.9453-1.0000-0.46670.001963-0.9454-1.0000-0.46670.001664-0.9455-1.0000-0.46670.001365-0.9457-1.0000-0.46670.001066-0.9458-1.0000-0.46670.000867-0.9458-1.0000-0.46670.000768-0.9459-1.0000-0.46670.000569-0.9460-1.0000-0.46670.000470-0.9461-1.0000-0.46670.0004最終程序
import argparse import csv import numpy as npdefmain():args = parser.parse_args()file, learningRate, threshold = args.data, float(args.learningRate), float(args.threshold) # save respective command line inputs into variables# read csv file and the last column is the target output and is separated from the input (X) as Ywith open(file) as csvFile:reader = csv.reader(csvFile, delimiter=',')X = []Y = []for row in reader:X.append([1.0] + row[:-1])Y.append([row[-1]])# Convert data points into float and initialise weight vector with 0s.n = len(X)X = np.array(X).astype(float)Y = np.array(Y).astype(float)W = np.zeros(X.shape[1]).astype(float)# this matrix is transposed to match the necessary matrix dimensions for calculating dot productW = W.reshape(X.shape[1], 1).round(4)# Calculate the predicted output valuef_x = calculatePredicatedValue(X, W)# Calculate the initial SSEsse_old = calculateSSE(Y, f_x)outputFile = 'solution_' + 'learningRate_' + str(learningRate) + '_threshold_' + str(threshold) + '.csv''''Output file is opened in writing mode and the data is written in the format mentioned in the post. After thefirst values are written, the gradient and updated weights are calculated using the calculateGradient function.An iteration variable is maintained to keep track on the number of times the batch linear regression is executedbefore it falls below the threshold value. In the infinite while loop, the predicted output value is calculated again and new SSE value is calculated. If the absolute difference between the older(SSE from previous iteration) and newer(SSE from current iteration) SSE is greater than the threshold value, then above process is repeated.The iteration is incremented by 1 and the current SSE is stored into previous SSE. If the absolute difference between the older(SSE from previous iteration) and newer(SSE from current iteration) SSE falls below the threshold value, the loop breaks and the last output values are written to the file.'''with open(outputFile, 'w', newline='') as csvFile:writer = csv.writer(csvFile, delimiter=',', quoting=csv.QUOTE_NONE, escapechar='')writer.writerow([*[0], *["{0:.4f}".format(val) for val in W.T[0]], *["{0:.4f}".format(sse_old)]])gradient, W = calculateGradient(W, X, Y, f_x, learningRate)iteration = 1whileTrue:f_x = calculatePredicatedValue(X, W)sse_new = calculateSSE(Y, f_x)if abs(sse_new - sse_old) > threshold:writer.writerow([*[iteration], *["{0:.4f}".format(val) for val in W.T[0]], *["{0:.4f}".format(sse_new)]])gradient, W = calculateGradient(W, X, Y, f_x, learningRate)iteration += 1sse_old = sse_newelse:breakwriter.writerow([*[iteration], *["{0:.4f}".format(val) for val in W.T[0]], *["{0:.4f}".format(sse_new)]])print("Output File Name: " + outputFiledefcalculateGradient(W, X, Y, f_x, learningRate):gradient = (Y - f_x) * Xgradient = np.sum(gradient, axis=0)# gradient = np.array([float("{0:.4f}".format(val)) for val in gradient])temp = np.array(learningRate * gradient).reshape(W.shape)W = W + tempreturn gradient, WdefcalculateSSE(Y, f_x):sse = np.sum(np.square(f_x - Y))return ssedefcalculatePredicatedValue(X, W):f_x = np.dot(X, W)return f_xif __name__ == '__main__':parser = argparse.ArgumentParser()parser.add_argument("-d", "--data", help="Data File")parser.add_argument("-l", "--learningRate", help="Learning Rate")parser.add_argument("-t", "--threshold", help="Threshold")main()? 這篇文章介紹了使用梯度下降法進行批線性回歸的數學概念。 在此,考慮了損失函數(在這種情況下為平方誤差總和)。 我們沒有看到最小化SSE的方法,而這是不應該的(需要調整學習率),我們看到了如何在閾值的幫助下使線性回歸收斂。
? 該程序使用numpy來處理數據,也可以使用python的基礎知識而不使用numpy來完成,但是它將需要嵌套循環,因此時間復雜度將增加到O(n * n)。 無論如何,numpy提供的數組和矩陣的內存效率更高。 另外,如果您喜歡使用pandas模塊,建議您使用它,并嘗試使用它來實現相同的程序。
? 希望您喜歡這篇文章。 謝謝閱讀。
總結
以上是生活随笔為你收集整理的模型训练 准确率下降_手写批量线性回归算法:在Python3中梯度下降方法实现模型训练的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 深圳python如何评价_Python分
- 下一篇: python创建列表_python创建与