• 转 机器学习ex1


    编者按:本系列系统总结Ng机器学习课程(http://cs229.stanford.edu/materials.html) Notes理论要点,并且给出所有课程exercise的作业code和实验结果分析。”游泳是游会的“,希望通过这个系列可以深刻理解机器学习算法,并且自己动手写出work高效的机器学习算法code应用到真实数据集做实验,理论和实战兼备。

    Part 1 Linear Regression

    1. Supervised Learning

    在Supervise Learning的Setting中,我们有若干训练数据(x^(i),y^(i)) i= 1,...,m ,这里i用于index training example。监督学习的任务就是要找到一个函数 (又称为模型或者假设hypothesis)H: X -> Y, 使得h(x)是相应值y的好的预测。整个过程可以描述为下图

    当待预测的目标变量是连续型数据时,我们称之为回归(regression)问题;当待预测的目标变量是离散型数据时,我们称之为分类(classification)问题。因此回归问题和分类问题是监督学习针对连续型数据预测和离散型数据预测的两种典型学习问题。

    2 Linear Regression

    一般而言,我们会用feature向量来描述训练数据X,我们用x_j^i来表示,其中j用于index feature, i用于index训练样本。在监督学习里面,我们需要找到一个最佳的预测函数h(x),比如我们可以选取feature的线性组合函数

    那么我们的问题就变成了要寻找最优的参数 heta可以使得预测的error最小。把这个函数用向量表示

    机器学习里面一般默认变量为列向量,因此这里是参数向量 heta的转置矩阵。同时我们还加上了”feature 0“即x_0 = 1 以便方便表示成为向量乘积的形式。为了寻找最优的参数 heta,我们可以最小化error function即cost function

    这个就是least-squares cost function,通过最小化这个函数来寻找最优参数。

    3 LMS算法

    为了寻找最优参数,我们可以随机初始化,然后沿着梯度慢慢改变参数值(需要改变 heta所有维),观察cost function值的变化,这就是梯度下降法的思想。假设我们只有一个训练样本(x,y), 对参数 heta_j求偏导数有

    我们可以得到下面的参数update rule

    其中alpha叫learning rate,用于调节每次迭代参数变化的大小,这就是LMS(least mean squares)算法。用直观的角度去理解,如果我们看到一个训练样本满足y^(i) - h(x(i))等于0,那么说明参数就不必再更新;反之,如果预测值error较大,那么参数的变化也需要比较大。

    如果我们有多个训练样本,比如有m个样本,每个样本用n个feature来描述,那么GD的update rule需要对n个feature对应的n个参数都做更新,有两种更新方式:batch gradient descent和stochastic/incremental gradient descent。对于前者,每次更新一轮参数 heta_j(注意n个参数需要同步更新才算完成一轮)需要都需要考虑所有的m个训练样本,即

    也就是每更新一个 heta_j我们需要计算所有m个训练样本的prediction error然后求和。而后者更新一轮参数 heta_j我们只需要考虑一个训练样本,然后逐个考虑完所有样本(因此是incremental的)即

    当训练样本size m非常大时,显然stochastic/incremental gradient descent会更有优势,因为每更新一轮参数不需要扫描所有的训练样本。

    我们也可以把cost function写出矩阵相乘的形式,即令

    则有

    因此代价函数J可以写成

    我们将J( heta)对向量 heta求梯度(对于向量求导,得到的是梯度,是有方向的,这里需要用到matrix calculus,比标量形式下求导麻烦一些,详见NG课程notes),令梯度为0可以直接得到极值点,也就是唯一全局最优解情形下的最值点(normal equations)

    这样可以避免迭代求解,直接得到最优的参数 heta值。

    3 编程实战

    (注:本部分编程习题全部来自Andrew Ng机器学习网上公开课)

    3.1 单变量的Linear Regression

    在单变量的Linear Regression中,每个训练样本只用一个feature来描述,例如某个卡车租赁公司分店的利润和当地人口总量的关系,给定若干人口总量和利润的训练样本,要求进行Linear Regression得到一条曲线,然后根据曲线对新的城市人口总量条件下进行利润的预测。

    主程序如下

    [plain] view plaincopy在CODE上查看代码片派生到我的代码片
    1. %% Initialization  
    2. clear ; close all; clc  
    3.   
    4. %% ==================== Part 1: Basic Function ====================  
    5. % Complete warmUpExercise.m   
    6. fprintf('Running warmUpExercise ...  ');  
    7. fprintf('5x5 Identity Matrix:  ');  
    8. warmUpExercise()  
    9.   
    10. fprintf('Program paused. Press enter to continue. ');  
    11. pause;  
    12.   
    13.   
    14. %% ======================= Part 2: Plotting =======================  
    15. fprintf('Plotting Data ... ')  
    16. data = load('ex1data1.txt');  
    17. X = data(:, 1); y = data(:, 2);  
    18. m = length(y); % number of training examples  
    19.   
    20. % Plot Data  
    21. % Note: You have to complete the code in plotData.m  
    22. plotData(X, y);  
    23.   
    24. fprintf('Program paused. Press enter to continue. ');  
    25. pause;  
    26.   
    27. %% =================== Part 3: Gradient descent ===================  
    28. fprintf('Running Gradient Descent ... ')  
    29.   
    30. X = [ones(m, 1), data(:,1)]; % Add a column of ones to x  
    31. theta = zeros(2, 1); % initialize fitting parameters  
    32.   
    33. % Some gradient descent settings  
    34. iterations = 1500;  
    35. alpha = 0.01;  
    36.   
    37. % compute and display initial cost  
    38. computeCost(X, y, theta)  
    39.   
    40. % run gradient descent  
    41. theta = gradientDescent(X, y, theta, alpha, iterations);  
    42.   
    43. % print theta to screen  
    44. fprintf('Theta found by gradient descent: ');  
    45. fprintf('%f %f  ', theta(1), theta(2));  
    46.   
    47. % Plot the linear fit  
    48. hold on; % keep previous plot visible  
    49. plot(X(:,2), X*theta, '-')  
    50. legend('Training data', 'Linear regression')  
    51. hold off % don't overlay any more plots on this figure  
    52.   
    53. % Predict values for population sizes of 35,000 and 70,000  
    54. predict1 = [1, 3.5] *theta;  
    55. fprintf('For population = 35,000, we predict a profit of %f ',...  
    56.     predict1*10000);  
    57. predict2 = [1, 7] * theta;  
    58. fprintf('For population = 70,000, we predict a profit of %f ',...  
    59.     predict2*10000);  
    60.   
    61. fprintf('Program paused. Press enter to continue. ');  
    62. pause;  
    63.   
    64. %% ============= Part 4: Visualizing J(theta_0, theta_1) =============  
    65. fprintf('Visualizing J(theta_0, theta_1) ... ')  
    66.   
    67. % Grid over which we will calculate J  
    68. theta0_vals = linspace(-10, 10, 100);  
    69. theta1_vals = linspace(-1, 4, 100);  
    70.   
    71. % initialize J_vals to a matrix of 0's  
    72. J_vals = zeros(length(theta0_vals), length(theta1_vals));  
    73.   
    74. % Fill out J_vals  
    75. for i = 1:length(theta0_vals)  
    76.     for j = 1:length(theta1_vals)  
    77.       t = [theta0_vals(i); theta1_vals(j)];      
    78.       J_vals(i,j) = computeCost(X, y, t);  
    79.     end  
    80. end  
    81.   
    82.   
    83. % Because of the way meshgrids work in the surf command, we need to   
    84. % transpose J_vals before calling surf, or else the axes will be flipped  
    85. J_vals = J_vals';  
    86. % Surface plot  
    87. figure;  
    88. surf(theta0_vals, theta1_vals, J_vals)  
    89. xlabel(' heta_0'); ylabel(' heta_1');  
    90.   
    91. % Contour plot  
    92. figure;  
    93. % Plot J_vals as 15 contours spaced logarithmically between 0.01 and 100  
    94. contour(theta0_vals, theta1_vals, J_vals, logspace(-2, 3, 20))  
    95. xlabel(' heta_0'); ylabel(' heta_1');  
    96. hold on;  
    97. plot(theta(1), theta(2), 'rx', 'MarkerSize', 10, 'LineWidth', 2);  

    首先load进训练数据,并且visualize出来

    然后需要实现两个函数 computeCost 和graientDescent,分别计算代价函数和对参数按照梯度方向进行更新,结合Linear Regression代价函数计算公式和参数更新Rule,我们可以实现如下

    [plain] view plaincopy在CODE上查看代码片派生到我的代码片
    1. function J = computeCost(X, y, theta)  
    2. %COMPUTECOST Compute cost for linear regression  
    3. %   J = COMPUTECOST(X, y, theta) computes the cost of using theta as the  
    4. %   parameter for linear regression to fit the data points in X and y  
    5.   
    6. % Initialize some useful values  
    7. m = length(y); % number of training examples  
    8.   
    9. % You need to return the following variables correctly   
    10. J = 0;  
    11.   
    12. % ====================== YOUR CODE HERE ======================  
    13. % Instructions: Compute the cost of a particular choice of theta  
    14. %               You should set J to the cost.  
    15.   
    16. J = 1/(2 * m) * (X * theta - y)' * (X * theta - y);  
    17.   
    18. % =========================================================================  
    19.   
    20. end  


    实现的时候要注意X是m行2列,theta是2行1列,y是m行1列。由于matlab默认矩阵是叉乘,要注意保证相乘的矩阵的维数满足叉乘的要求。参数更新函数如下

    [plain] view plaincopy在CODE上查看代码片派生到我的代码片
    1. function [theta, J_history] = gradientDescent(X, y, theta, alpha, num_iters)  
    2. %GRADIENTDESCENT Performs gradient descent to learn theta  
    3. %   theta = GRADIENTDESENT(X, y, theta, alpha, num_iters) updates theta by   
    4. %   taking num_iters gradient steps with learning rate alpha  
    5.   
    6. % Initialize some useful values  
    7. m = length(y); % number of training examples  
    8. J_history = zeros(num_iters, 1);  
    9.   
    10. for iter = 1:num_iters  
    11.   
    12.     % ====================== YOUR CODE HERE ======================  
    13.     % Instructions: Perform a single gradient step on the parameter vector  
    14.     %               theta.   
    15.     %  
    16.     % Hint: While debugging, it can be useful to print out the values  
    17.     %       of the cost function (computeCost) and gradient here.  
    18.     %  
    19.     % Batch gradient descent  
    20.     Update = 0;  
    21.     for i = 1:m  
    22.         Update = Update + alpha/m * (y(i) - X(i,:) * theta) * X(i, :)';  
    23.     end   
    24.     theta = theta + Update;  
    25.   
    26.     % ============================================================  
    27.   
    28.     % Save the cost J in every iteration      
    29.     J_history(iter) = computeCost(X, y, theta);  
    30.   
    31. end  
    32.   
    33. end  


    这里用的是Batch Gradient Descent,也就是每更新一次参数都需要扫描所有m个训练样本。Update就是每次参数的变化量,需要对所有training example的训练误差进行求和。 每次更新参数后重新计算代价函数,把所有历史的cost记录保存在J_history中。经过1500次迭代,我们可以输出求的的参数theta,画出拟合的曲线,并且对新的人口来预测利润值,即

    [plain] view plaincopy在CODE上查看代码片派生到我的代码片
    1. Running Gradient Descent ...  
    2.   
    3. ans =  
    4.   
    5.    32.0727  
    6.   
    7. Theta found by gradient descent: -3.630291 1.166362   
    8. For population = 35,000, we predict a profit of 4519.767868  
    9. For population = 70,000, we predict a profit of 45342.450129  
    10. Program paused. Press enter to continue.  
    11. Visualizing J(theta_0, theta_1) ...  


    拟合出的曲线如下图

    我们把cost function J的值在(theta_0, theta_1)上进行visualization可以得到

    下面这张图是在(theta_0,theta_1)上的投影等高线图,红叉处就是GD收敛到的最小值处。对于linear regression只有全局最优解,所以这个也是我们想要的最优参数。

    3.2 多变量的Linear Regression

    如果每个训练样本用多个feature来描述,这就是多变量的Linear Regression问题。比如我们想根据房子的面积和卧室个数来预测房子的价格,那么现在每个训练样本就是用2个feature来描述。主程序如下

    [plain] view plaincopy在CODE上查看代码片派生到我的代码片
    1. %% Initialization  
    2.   
    3. %% ================ Part 1: Feature Normalization ================  
    4.   
    5. %% Clear and Close Figures  
    6. clear ; close all; clc  
    7.   
    8. fprintf('Loading data ... ');  
    9.   
    10. %% Load Data  
    11. data = load('ex1data2.txt');  
    12. X = data(:, 1:2);  
    13. y = data(:, 3);  
    14. m = length(y);  
    15.   
    16. % Print out some data points  
    17. fprintf('First 10 examples from the dataset:  ');  
    18. fprintf(' x = [%.0f %.0f], y = %.0f  ', [X(1:10,:) y(1:10,:)]');  
    19.   
    20. fprintf('Program paused. Press enter to continue. ');  
    21. pause;  
    22.   
    23. % Scale features and set them to zero mean  
    24. fprintf('Normalizing Features ... ');  
    25.   
    26. [X mu sigma] = featureNormalize(X);  
    27.   
    28. % Add intercept term to X  
    29. X = [ones(m, 1) X];  
    30.   
    31.   
    32. %% ================ Part 2: Gradient Descent ================  
    33.   
    34. % ====================== YOUR CODE HERE ======================  
    35. % Instructions: We have provided you with the following starter  
    36. %               code that runs gradient descent with a particular  
    37. %               learning rate (alpha).   
    38. %  
    39. %               Your task is to first make sure that your functions -   
    40. %               computeCost and gradientDescent already work with   
    41. %               this starter code and support multiple variables.  
    42. %  
    43. %               After that, try running gradient descent with   
    44. %               different values of alpha and see which one gives  
    45. %               you the best result.  
    46. %  
    47. %               Finally, you should complete the code at the end  
    48. %               to predict the price of a 1650 sq-ft, 3 br house.  
    49. %  
    50. % Hint: By using the 'hold on' command, you can plot multiple  
    51. %       graphs on the same figure.  
    52. %  
    53. % Hint: At prediction, make sure you do the same feature normalization.  
    54. %  
    55.   
    56. fprintf('Running gradient descent ... ');  
    57.   
    58. % Choose some alpha value  
    59. alpha = 0.01;  
    60. num_iters = 1000;  
    61.   
    62. % Init Theta and Run Gradient Descent   
    63. theta = zeros(3, 1);  
    64. [theta, J_history] = gradientDescentMulti(X, y, theta, alpha, num_iters);  
    65.   
    66. % Plot the convergence graph  
    67. figure;  
    68. plot(1:numel(J_history), J_history, '-b', 'LineWidth', 2);  
    69. xlabel('Number of iterations');  
    70. ylabel('Cost J');  
    71.   
    72. % Display gradient descent's result  
    73. fprintf('Theta computed from gradient descent:  ');  
    74. fprintf(' %f  ', theta);  
    75. fprintf(' ');  
    76.   
    77. % Estimate the price of a 1650 sq-ft, 3 br house  
    78. % ====================== YOUR CODE HERE ======================  
    79. % Recall that the first column of X is all-ones. Thus, it does  
    80. % not need to be normalized.  
    81. x_predict = [1 1650 3];  
    82. for i=2:3  
    83.     x_predict(i) = (x_predict(i) - mu(i-1)) / sigma(i-1);  
    84. end  
    85. price = x_predict * theta;  
    86.   
    87. % ============================================================  
    88.   
    89. fprintf(['Predicted price of a 1650 sq-ft, 3 br house ' ...  
    90.          '(using gradient descent):  $%f '], price);  
    91.   
    92. fprintf('Program paused. Press enter to continue. ');  
    93. pause;  
    94.   
    95. %% ================ Part 3: Normal Equations ================  
    96.   
    97. fprintf('Solving with normal equations... ');  
    98.   
    99. % ====================== YOUR CODE HERE ======================  
    100. % Instructions: The following code computes the closed form   
    101. %               solution for linear regression using the normal  
    102. %               equations. You should complete the code in   
    103. %               normalEqn.m  
    104. %  
    105. %               After doing so, you should complete this code   
    106. %               to predict the price of a 1650 sq-ft, 3 br house.  
    107. %  
    108.   
    109. %% Load Data  
    110. data = csvread('ex1data2.txt');  
    111. X = data(:, 1:2);  
    112. y = data(:, 3);  
    113. m = length(y);  
    114.   
    115. % Add intercept term to X  
    116. X = [ones(m, 1) X];  
    117.   
    118. % Calculate the parameters from the normal equation  
    119. theta = normalEqn(X, y);  
    120.   
    121. % Display normal equation's result  
    122. fprintf('Theta computed from the normal equations:  ');  
    123. fprintf(' %f  ', theta);  
    124. fprintf(' ');  
    125.   
    126.   
    127. % Estimate the price of a 1650 sq-ft, 3 br house  
    128. % ====================== YOUR CODE HERE ======================  
    129. x_predict = [1 1650 3];  
    130. price = x_predict * theta;  
    131. % ============================================================  
    132.   
    133. fprintf(['Predicted price of a 1650 sq-ft, 3 br house ' ...  
    134.          '(using normal equations):  $%f '], price);  

    3.2.1 Feature Normalization

    通过观察feature的特征可以知道,房子的面积的数值大约是卧室个数数值的1000倍左右,当遇到不同feature的数值范围差异非常显著的情况,需要先进行feature normalization,这样可以加快learning算法的收敛。要进行Feature Normalization,需要首先对每一列feature值计算均值mu和标准差sigma,然后normalization/scale 之后的feature值x'与原始feature值x满足  x' = (x - mu) / sigma 。即把原始的feature减去均值然后除以标准差。因此我们可以这样实现feature normalization的函数

    3.2.2 Gradient Descent

    这一步同样需要实现计算代价函数和更新参数的函数,对于多变量的线性回归,其代价函数也可以写成如下的向量化表示的形式

    上面给出的单变量情形的代价函数和参数update rule同样适用于多变量情形,只是现在X有很多列,同样支持。注意这个时候没有办法在( heta_0, heta_1, heta_2)上面可视化代价函数J,一共有四维。但是可以画出代价函数J随迭代次数的变化曲线如下

    这里设置的learning rate alpha = 0.01,迭代1000次,可以看出在400次左右时代价函数J就几乎收敛,不再变化。我们也可以调节learning rate alpha, 选取合适的learning rate很重要,选得太小收敛很慢,选得太大有可能无法收敛(每次迭代参数变化太大,没法找到极值点)Ng建议选取alpha时按照log scale,比如不断除以3,0.3 , 0.1 , 0.03 , 0.01 ...

    3.2.3 Normal Equations

    Alternately, 我们也可以直接用下面这个公式来计算最优的 heta,推导过程是代价函数对参数向量 heta求导数,令导数为0.

    函数实现如下

    [plain] view plaincopy在CODE上查看代码片派生到我的代码片
    1. function [theta] = normalEqn(X, y)  
    2. %NORMALEQN Computes the closed-form solution to linear regression   
    3. %   NORMALEQN(X,y) computes the closed-form solution to linear   
    4. %   regression using the normal equations.  
    5.   
    6. theta = zeros(size(X, 2), 1);  
    7.   
    8. % ====================== YOUR CODE HERE ======================  
    9. % Instructions: Complete the code to compute the closed form solution  
    10. %               to linear regression and put the result in theta.  
    11. %  
    12. theta = inv(X'* X)*X'*y;  
    13. % ============================================================  
    14.   
    15. end  

    注意在GD中做预测时需要先对feature做normalization;在NE中做预测时不需要最feature做normalization。


    综上所述,程序会先基于batch gradient descent 求最优 heta,然后对测试样本预测房价(注意feature normalization);然后基于normal equation直接算 heta,然后对测试样本预测房价。全部输出结果如下

    [plain] view plaincopy在CODE上查看代码片派生到我的代码片
    1. Normalizing Features ...  
    2. Running gradient descent ...  
    3. Theta computed from gradient descent:   
    4.  340397.963535   
    5.  109848.008460   
    6.  -5866.454085   
    7.   
    8. Predicted price of a 1650 sq-ft, 3 br house (using gradient descent):  
    9.  $293237.161479  
    10. Program paused. Press enter to continue.  
    11. Solving with normal equations...  
    12. Theta computed from the normal equations:   
    13.  89597.909543   
    14.  139.210674   
    15.  -8738.019112   
    16.   
    17. Predicted price of a 1650 sq-ft, 3 br house (using normal equations):  
    18.  $293081.464335  

    两次求的参数不同,因为前者有feature normalization,后者没有。对1650 sq-ft, 3 br house的房子预测的房价都在29万美元左右。

  • 相关阅读:
    背景大图隔几秒切换(非轮播,淡入淡出)--变形金刚joy007 项目总结
    call(京基填小票拍照片)
    加载图片、倒计时--Columbia项目总结
    kellogg项目总结
    js 跨域
    js 继承inheritance/extends
    一号店分享会
    日历,类似旅行网站的酒店入住
    js 数组的判断
    Building a Non-blocking TCP server using OTP principles
  • 原文地址:https://www.cnblogs.com/lixiang-/p/4895289.html
Copyright © 2020-2023  润新知