# ML-Andrew Ng 学习笔记(2) Cost Function & Gradient Descent **Published by:** [jasonyang](https://paragraph.com/@jasonyang/) **Published on:** 2023-04-27 **URL:** https://paragraph.com/@jasonyang/ml-andrew-ng-2-cost-function-gradient-descent ## Content 笔者今年只有大一,虽然课程内有讲ml但是觉得不应止于此,想额外学一部分,故见解不到位的也请谅解 以下将会讨论成本函数(cost function)和梯度下降(gradient descent)的相关问题。 A.成本函数:用于衡量假设函数h(x)准确性的工具 给出一份数据,能够拟合出多条直线,有着多组θ_0, θ_1,但为了更精准地预测,需要找到其中一组,使得数据点尽可能多地落在直线上或者其附近,因此需要成本函数。 cost function ** 举例**:单变量线性回归(univariate linear regression) 单变量是对于x而言的 to minimize x_i, y_i为第i组的样本 1/2m 作用仅仅是对后面整体求导时,作为指数的2乘下来与1/2抵消,不会影响到求θ的最小值 "To make the derivations mathematically more convenient" cost function (or Squared error function) ** 几何理解:** 对于简化版h(x)=θ_1*x, 实质上是各组h(x_1)=θ_1*x_1与真实值y_1之间高度差绝对值的平方之和乘1/2样本数量 ** 可视化:** 对于h(x)=θ_0+θ_1*x, 凸函数(convex function) 对于线性回归总会是这样的凸函数,只有全局最优解 contour plots 右图线上的点虽然有着不同的θ_1, θ_0,但对应的J值是相同的 可看做上方凸函数图像的各个截面 椭圆最中心的点即为成本函数值最小处 计算cost(梯度下降步骤1): equation 2 def compute_cost(x,y,w,b): #equation 2 (for univariate) m = x.shape[0] cost = 0 for i in range(m): f_wb = w * x[i] + b #one feature cost = cost + (f_wb - y[i])** 2 total_cost = 1/(2 * m) * cost return total_cost def compute_cost(X, y, w, b): #equation 2 (for multi-var) m = X.shape[0] cost = 0.0 for i in range(m): f_wb_i = np.dot(X[i], w) + b #multiple features cost = cost + (f_wb_i - y[i]) **2 cost = cost / (2 * m) return cost 这里只能算出数据集中总的cost值,但如何具体得到使J值最小的θ_1, θ_0,需要用到梯度下降 B.梯度下降:是为了找到目标点的一种方法,透过一步步靠近目标的方式,最终找到极近似目标的函数 已有的和目标 ** 可视化说明1:** 想要从山顶想要最快速地走到山脚,因此需要找到最陡峭的路前进,对于代价函数来说,路即为斜率k 示意图 但存在问题:出发点稍微偏离一点,便可以得到完全不同的局部最优解 “实际应用中,评估所有可能的参数通常不能找到全局最优解。而是使用优化算法找到解,虽然可能不一定是全局最优的,但足够满足目标。另一种办法是用更高级的技术,如SGD或者Adam。” ** 具体算法**: 单一特征或多特征(也就是x的数量) α为学习速率(learning rate),改变该值对应着下坡时的跨度 对***θ_1, θ_0 (w,b)的同步更新*(simultaneously update) 个人理解: θ_1, θ_0可以看作下坡时的向左向右,减去的α和导数项之积对于θ_1, θ_0是完全相同的,即重新调整的方向的跨度是相同的。 正确处理 错误处理:这样处理的问题在于,计算θ 计算gradient(梯度下降步骤2): equation 4 & 5 def compute_gradient (x,y,w,b): #equation 4,5 (for univariate) m = x.shape[0] dj_dw = 0 dj_db = 0 for i in range(m): f_wb = w * x[i] + b dj_dw_i = (f_wb - y[i]) * x[i] dj_db_i = f_wb - y[i] dj_db += dj_db_i dj_dw += dj_dw_i dj_dw = dj_dw /m dj_db = dj_db /m return dj_dw , dj_db def compute_gradient(X, y, w, b): #equation 4,5 (for multi-var) m,n = X.shape #(# of examples, # of features) dj_dw = np.zeros((n,)) dj_db = 0. for i in range(m): err = (np.dot(X[i], w) + b) - y[i] for j in range(n): dj_dw[j] = dj_dw[j] + err * X[i, j] dj_db = dj_db + err dj_dw = dj_dw / m dj_db = dj_db / m return dj_db, dj_dw 现在有了计算cost和gradient的函数,就可以进行descent的过程 梯度下降步骤3: equation 3 #equation 3 def gradient_descent(x, y, w_in, b_in, alpha, num_iters, cost_function, gradient_function): """ Args: x (ndarray (m,)) : Data, m examples y (ndarray (m,)) : target values w_in,b_in (scalar): initial values of model parameters Returns: w (scalar): Updated value b (scalar): Updated value J_history (List): History of cost values p_history (list): History of parameters [w,b] """ w = copy.deepcopy(w_in) # 避免影响w_in。深拷贝,确保每个对象的独立性,从而避免在原对象和副本之间共享对象所导致的潜在问题) J_history = [] p_history = [] b = b_in w = w_in for i in range(num_iters): dj_dw, dj_db = gradient_function(x, y, w , b) # Update Parameters using equation (3) above b = b - alpha * dj_db w = w - alpha * dj_dw # Save cost J at each iteration if i<100000: # prevent resource exhaustion J_history.append( cost_function(x, y, w , b)) #返回total_cost p_history.append([w,b]) # 控制代码的执行频率,确保某些代码只在特定的迭代次数执行。 if i % math.ceil(num_iters/10) == 0: print(f"Iteration {i:4}: Cost {J_history[-1]:0.2e} ", f"dj_dw: {dj_dw: 0.3e}, dj_db: {dj_db: 0.3e} ", f"w: {w: 0.3e}, b:{b: 0.5e}") return w, b, J_history, p_history #return for graphing def gradient_descent(X, y, w_in, b_in, cost_function, gradient_function, alpha, num_iters): """ Args: X (ndarray (m,n)) : Data, m examples with n features y (ndarray (m,)) : target values w_in (ndarray (n,)), b_in (scalar) : initial parameters Returns: w (ndarray (n,)) : Updated values b (scalar) : Updated value """ # An array to store cost J and w's at each iteration primarily for graphing later J_history = [] w = copy.deepcopy(w_in) #avoid modifying global w within function b = b_in for i in range(num_iters): dj_db,dj_dw = gradient_function(X, y, w, b) w = w - alpha * dj_dw b = b - alpha * dj_db # Save cost J at each iteration if i<100000: # prevent resource exhaustion J_history.append( cost_function(X, y, w, b)) # 控制代码的执行频率,确保某些代码只在特定的迭代次数执行。 if i% math.ceil(num_iters / 10) == 0: print(f"Iteration {i:4d}: Cost {J_history[-1]:8.2f} ") return w, b, J_history #return for graphing 可视化说明2: a)第一种情况:斜率为正值 正斜率时 对θ进行更新时,由于斜率为正,对应的导数为正数,因此减去该值后是在对θ向后调整 每次调整后会得到新的斜率,新的斜率相对于调整前的会更小,因此新的调整幅度会更小最终找到局部最优解 b)第二种情况:斜率为负值 负斜率时 对θ进行更新时,由于斜率为负,对应的导数为负数,因此减去该值后是在对θ向前调整 新的调整幅度同样会越来越小,最终逼近目标 c)第三种情况:斜率为0,已经处在局部或者全局最优处时 斜率为0 此时对θ更新时,后面的减数由于斜率为0,因此θ的值不变,这也能说明已经达到最优点 ** 对α的选取:** a)不应过小 过小时对于下降过于缓慢,甚至可能会出现几乎停滞的状态 b)不应过大 过大时跨步过大,会越来越远离目标点 假设绿点为初始点,此时的导数值为一个较小的负值,但由于α过大,导致绿点对应的θ加上了一个比较大的数,得到紫点; 紫点对应的导数值为一个较大的正值,同样由于α过大,使得此时的θ减去一个更大的数字,得到橘点; 不断地滚雪球最终离目标点越来越远 (本来想着具体算算,纸上画图、用desmos画图,结果研究了半天,纸上演算一整发现好麻烦,结果用脑子想想道理其实好简单==) c) 可能的问题 学习率过大可能会导致,或者代码有误,如:w_1 = w_1 +αd_1 因此可以先使用非常小的α迭代数次,确定图像趋势正确后,再提高 对梯度下降的优化: 特征放缩(Feature Scaling): 使下降速度更快 能够消除特征之间的量纲差异性,使得不同特征更具有可比性 (size in feet量级可能是k,而#bedrooms则是个位数,前者会对结果产生较大影响,后者则有可能会被忽略) 同时也能让数据足够离散(不是主要目的) 放缩与不放缩的对比 方案1:除以取值范围最大值 300≤x1≤2000 方案2:均值归一化(Mean Normalization) 300≤ x1≤2000 方案3:Z-score 标准化 300≤ x1≤2000 但放缩结果并无强制要求,接近-1≤ x_j ≤ 1的范围 z-score normalization处理 c)固定?不固定? α不变的情况下随着与其相乘的导数值不断变化,整体是一直动态调整的,所以在最开始设置好后不会出现上述过大过小的情况的话,其实没有必要在训练过程中调整α? “通常在训练开始前设置好并在过程中保存不变,但对于某些情况可能需要在期间进行调整。” 梯度下降的种类: a) 批量梯度下降法(Batch Gradient Descent) 对整个样本集进行遍历,更新参数时使用所以的样本来完成这一操作 batch *n.*一批,一批生产量;*v.*分批处理 b)随机梯度下降法(Stochastic Gradient Descent) 选用一个样本进行梯度下降,对于过大样本使用a方法训练速度过慢 但解不一定最优 c)小批量梯度下降法(Mini-batch Gradient Descent) 上述两种的折衷 细分的种类以后课程内或者课程外学到了再新补充吧 参考来源: https://datascience.stackexchange.com/questions/52157/why-do-we-have-to-divide-by-2-in-the-ml-squared-error-cost-function https://www.cnblogs.com/pinard/p/5970503.html https://www.coursera.org/learn/machine-learning ## Publication Information - [jasonyang](https://paragraph.com/@jasonyang/): Publication homepage - [All Posts](https://paragraph.com/@jasonyang/): More posts from this publication - [RSS Feed](https://api.paragraph.com/blogs/rss/@jasonyang): Subscribe to updates