给定300个样本点(x, y)。拟合直线:
设直线方程为y = w*x + b
其中:x,y是给定的样本点,作为训练集。w和b是待拟合的参数。
该问题可以转化为,优化函数 f(w, b) = y - w*x - b
使用平方损失,转化为优化:f(w, b) = (y - w*x -b)^2
求w的梯度为: grad_w = -x * 2(y - w*x -b)
求b的梯度为:grad_b = -1 * 2(y - w*x -b)
再使用:
w = w - lr * grad_w
b = b- lr * grad_b
优化这两个变量。
import numpy as npimport randomimport cv2def fit_line_by_grad():gt_x = range(300)gt_y = [2*x+4 + 20 * np.random.random() for x in gt_x]print("train sample: {}".format(len(gt_x)))# y = w * x + b ==> f(w, b) = y - w * x -b ==> f(w, b) = (y - w * x -b)^2# ==> grad_w = -x * 2 (y - w * x -b), grad_b = -1 * 2 (y - w * x -b)iteration = 10000lr = 0.000001w = 0.0001b = 0for i in range(iteration):i = i % len(gt_x)x = gt_x[i]y = gt_y[i]grad_w = - x * 2 * (y - w * x -b)grad_b = -1 * 2 * (y - w * x -b)w = w - lr * grad_wb = b - lr * grad_bprint("y = {}*x + {}".format(w, b))img = np.zeros([500, 500, 3], dtype=np.uint8)for gt in zip(gt_x, gt_y):x, y = [int(i) for i in gt]cv2.circle(img, (x, y), 3, (0, 255, 0), 1)fit1 = (0, int(w * 0 + b))fit2 = (300, int(w * 300 + b))cv2.line(img, fit1, fit2, (0, 0, 255), 3)cv2.namedWindow("res", 0)cv2.imshow("res", img)key = cv2.waitKey(0)if key == 27:exit()fit_line_by_grad()
最终的拟合效果为:
如果觉得《梯度下降法拟合直线》对你有帮助,请点赞、收藏,并留下你的观点哦!