온라인 강의 플랫폼 코세라의 창립자인 앤드류 응 (Andrew Ng) 교수는 인공지능 업계의 거장입니다. 그가 스탠퍼드 대학에서 머신 러닝 입문자에게 한 강의를 그대로 코세라 온라인 강의 (Coursera.org)에서 무료로 배울 수 있습니다. 이 강의는 머신러닝 입문자들의 필수코스입니다. 인공지능과 머신러닝을 혼자 공부하면서 자연스럽게 만나게 되는 강의입니다.
In the first half of the exercise, you will implement regularized linear regression to predict the amount of water flowing out of a dam using the change of water level in a reservoir. In the next half, you will go through some diagnostics of debugging learning algorithms and examine the effects of bias v.s. variance.
The provided script, ex5.m, will help you step through this exercise.
이번 실습의 전반부에서 저수지의 수위 변화와 댐의 방수량을 예측하기 위해 정규화된 선형 회귀를 구현합니다. 후반부에서 편향과 분산의 영향을 검사하고 학습 알고리즘을 디버깅하는 진단을 합니다. 실습 진행은 ex5.m 파일을 중심으로 진행합니다.
We will begin by visualizing the dataset containing historical records on the change in the water level, x, and the amount of water flowing out of the dam, y.
This dataset is divided into three parts:
A training set that your model will learn on: X, y
A cross validation set for determining the regularization parameter: Xval, yval
A test set for evaluating performance. These are “unseen” examples which your model did not see during training: Xtest, ytest
The next step of ex5.m will plot the training data (Figure 1). In the following parts, you will implement linear regression and use that to fit a straight line to the data and plot learning curves. Following that, you will implement polynomial regression to find a better fit to the data.
먼저 수위 x의 변화와 댐의 방수량에 대한 기록을 나타내는 데이터를 시각화합니다.
데이터 셋을 세 부분으로 나눕니다.
학습 셋 (Training Set): 모델이 데이터를 학습 (X, y)
교차 검증 셋 (Cross Validation set) : 정규화 파라미터를 결정(Xval, yval)
테스트 셋 (Test Set): 학습에 사용하지 않은 학습 에제 (Xtest, ytest)
ex5.m 파일은 학습 데이터를 도식화하고, 선형 회귀를 구현하고, 데이터에 적합한 직선을 계산하고 학습 곡선을 그립니다. 그리고, 직선보다 데이터에 더 적합한 다항 회귀를 구현합니다.
(1) 데이터 업로드 및 기본 변수 설정
clear ; % 옥타브 프로그램에 모든 변수를 제거
close all; % 터미널 이외의 창을 닫음
clc % 터미널을 깨끗이 정리
load ('ex5data1.mat'); % 옥타브 프로그램으로 데이터 업로드
[m,n] = size(X); % 학습 예제의 수와 피처의 수를 정의
옥타브 프로그램에서 다음과 같이 실행합니다.
>> load ('ex5data1.mat'); % 6개의 변수가 자동으로 생성
>> [m,n] = size(X); % 2개의 변수 추가 생성
>> whos
Variables in the current scope:
Attr Name Size Bytes Class
==== ==== ==== ===== =====
X 12x1 96 double
Xtest 21x1 168 double
Xval 21x1 168 double
m 1x1 8 double
n 1x1 8 double
y 12x1 96 double
ytest 21x1 168 double
yval 21x1 168 double
Total is 110 elements using 880 bytes
옥타브 프로그램에 로딩한 ex5data1.mat 파일은 자동으로 학습 셋 (X, y), 교차 검증 셋 (Xval, yval), 테스트 셋 (Xtest, ytest)을 생성합니다.
(2) 데이터 시각화
옥타브 프로그램에서 학습 셋 (X,y)에 있는 12개의 학습 예제를 도식화합니다.
plot(X, y, 'rx', 'MarkerSize', 5, 'LineWidth', 1.5);
x축과 y축에 레이블을 붙입니다.
xlabel('Change in water level (x)');
ylabel('Water flowing out of the dam (y)');
Recall that regularized linear regression has the following cost function:
where λ is a regularization parameter which controls the degree of regu- larization (thus, help preventing overfitting). The regularization term puts a penalty on the overal cost J. As the magnitudes of the model parameters θj increase, the penalty increases as well. Note that you should not regularize the θ0 term. (In Octave/MATLAB, the θ0 term is represented as theta(1) since indexing in Octave/MATLAB starts from 1).
You should now complete the code in the file linearRegCostFunction.m. Your task is to write a function to calculate the regularized linear regression cost function. If possible, try to vectorize your code and avoid writing loops. When you are finished, the next part of ex5.m will run your cost function using theta initialized at [1; 1]. You should expect to see an output of 303.993.
정규화된 선형 회귀의 비용 함수입니다. 정규화 파라미터 λ는 과적합을 방지합니다. 정규화 항은 비용 함수 J(θ)에 페널티를 부과합니다. 파라미터 θj의 크기가 증가할수록 페널티도 증가합니다. θ0는 정규화하지 않습니다. (옥타브 프로그램은 1부터 시작하기 때문에 θ0는 theta(1)입니다.)
linearRegCostFuction.m 파일의 미완성 코드를 완료합니다. 정규화된 선형 회귀 비용 함수를 계산하는 함수를 작성합니다. 코드는 벡터화하고 루프를 사용하지 마십시오. ex5.m 파일은 Theta를 [1;1]로 초기화하고 303.993을 출력할 것입니다.
(1) 데이터 업로드 및 기본 변수 설정
clear ; % 옥타브 프로그램에 모든 변수를 제거
close all; % 터미널 이외의 창을 닫음
clc % 터미널을 깨끗이 정리
load ('ex5data1.mat'); % 옥타브 프로그램으로 데이터 업로드
[m,n] = size(X); % 학습 예제의 수와 피처의 수를 정의
(2) linearRegCostFucion.m 파일 분석
function [J, grad] = linearRegCostFunction(X, y, theta, lambda)
%LINEARREGCOSTFUNCTION 비용과 정규화된 선형 회귀와 비용 함수와 기울기를 계산
%
% [J, grad] = LINEARREGCOSTFUNCTION(X, y, theta, lambda) computes the
% cost of using theta as the parameter for linear regression to fit the
% data points in X and y. Returns the cost in J and the gradient in grad
% 변수 초기화
m = length(y); % 학습 예제의 수
% 반환할 값 초기화
J = 0; % 비용 함수 J의 값
grad = zeros(size(theta)); % 경사 하강법에 의한 경사
% ====================== YOUR CODE HERE ======================
% Instructions: 비용과 정규화된 선형 회귀와 비용 함수와 기울기를 계산
% J와 grad를 설정
%
% =========================================================================
grad = grad(:);
end
(3) 비용 함수 J(θ)를 계산하는 코드 작성
우선 학습 데이터 X에 바이어스 항을 추가합니다.
X = [ones(m,1) X];
옥타브 프로그램에서 다음과 같이 입력합니다.
>> X
X =
-15.9368
-29.1530
36.1895
37.4922
-48.0588
-8.9415
15.3078
-34.7063
1.3892
-44.3838
7.0135
22.7627
>> X = [ones(m,1) X]
X =
1.0000 -15.9368
1.0000 -29.1530
1.0000 36.1895
1.0000 37.4922
1.0000 -48.0588
1.0000 -8.9415
1.0000 15.3078
1.0000 -34.7063
1.0000 1.3892
1.0000 -44.3838
1.0000 7.0135
1.0000 22.7627
파라미터 벡터를 theta를 [1;1]로 초기화합니다.
theta = [1;1];
옥타브 프로그램에서 다음과 같이 입력합니다.
>> theta = [1;1];
>> theta
theta =
1
1
비용 함수 J(θ)와 정규화된 비용 함수 J(θ)를 계산하는 공식은 다음과 같습니다.
비용 함수 J(θ)를 계산하는 코드를 공식에 따라 작성합니다. For 루프와 sum()함수를 사용하지 않고 벡터화 구현을 했을 때 가장 간단한 코드는 다음과 같습니다.
J = 1/(2*m) *(X*theta - y)'*(X*theta - y) ;
X는 12 X 2차원 벡터이고, thea는 2 X 1차원 벡터입니다. 가설 hθ(x)를 계산하는 두 행렬의 곱셈 결과는 12 X 1차원 벡터입니다. y는 12 X 1차원 벡터이고 행렬 뺄셈을 하면 성분 간에 뺄셈이 되어서 X*theta - y는 12 X 1차원 벡터입니다.
벡터의 성분을 제곱하는 방법은 두 가지입니다. 첫 번째는 행렬 성분을 제곱하고 모든 열의 행렬 성분을 더하는 방법입니다. 코드는 다음과 같습니다.
sum(A.^2);
>> A = [4; 3; 2]
A =
4
3
2
>> A .^2
ans =
16
9
4
>> sum (A .^2)
ans = 29
두 번째는 벡터 곱셈을 이용하는 것입니다.
>> A
A =
4
3
2
>> A'*A
ans = 29
물론, 벡터가 아닌 행렬은 제곱하는 방법에 사용할 수 없습니다. 전혀 다른 값이 됩니다.
>> A = [4 2 ; 4 2; 3 3]
A =
4 2
4 2
3 3
>> A'
ans =
4 4 3
2 2 3
>> A'*A
ans =
41 25
25 17
결과값이 벡터인지 행렬인지에 따라 선호하는 방법을 사용할 수 있습니다. 첫 번째 방법은 벡터와 행렬에 상관없이 사용할 수 있고, 두 번째 방법은 벡터인 경우만 사용할 수 있습니다.
옥타브 프로그램에 다움과 같이 입력합니다.
clear ; close all; clc
load ('ex5data1.mat');
[m,n] = size(X);
X = [ones(m,1) X];
theta = [1;1];
J = 1/(2*m) *(X*theta - y)'*(X*theta - y)
J = 303.95
J = 1/(2*m)*sum((X*theta - y) .^2)
J = 303.95
두 식의 결과가 같다는 것을 확인할 수 있습니다.
(4) 정규화된 비용 함수 J(θ)를 계산하는 코드 작성
정규화 항이 포함된 비용 함수 J(θ)의 공식은 다음과 같습니다.
정규화 항 코드는 다음과 같이 작성합니다. 정규화 항은 바이어스 항을 제외합니다. 파라미터 theta의 첫 번째 성분인 theta(1)을 제외하기 위해 theta(2:end)를 사용합니다. theta는 2차원 벡터이고 첫 번째 성분을 제외하여 실수입니다. 여기서도 벡터 곱셈을 활용하여 theta를 제곱합니다.
reg = lambda /(2*m) *theta(2:end)'*theta(2:end) ; % 바이어스 항을 제외
정규화 항을 정규화지 않은 비용 함수 J(θ)에 추가합니다.
J = J + reg % 정규화 항에 비용 함수를 합산
옥타브 프로그램에 다움과 같이 입력합니다.
>> lambda = 1;
>> reg = lambda /(2*m) *theta(2:end)'*theta(2:end) ;
>> J = J + reg
J = 303.99
문제에서 제시한 비용과 동일합니다.
function [J, grad] = linearRegCostFunction(X, y, theta, lambda)
%LINEARREGCOSTFUNCTION 비용과 정규화된 선형 회귀와 비용 함수와 기울기를 계산
%
% [J, grad] = LINEARREGCOSTFUNCTION(X, y, theta, lambda)
% 데이터 X와 y, 선형 회귀 파라미터 theta, 정규화 파라미터 lambda로 계산
% 계산 결과인 비용 J와 기울기 grad를 반환
%
% 변수 초기화
m = length(y); % 학습 예제의 수
% 반환할 값 초기화
J = 0; % 비용 함수 J의 값
grad = zeros(size(theta)); % 경사 하강법에 의한 경사
% ====================== YOUR CODE HERE ======================
% Instructions: 비용과 정규화된 선형 회귀와 비용 함수와 기울기를 계산
% J와 grad를 설정
%
J = 1/(2*m) *(X*theta - y)'*(X*theta - y) ;
reg = lambda /(2*m) *theta(2:end)'*theta(2:end) ;
J = J + reg;
% =========================================================================
grad = grad(:);
end
ex5.m 파일은 linearRegCostFunction.m 파일을 다음과 같이 호출합니다.
clear ; close all; clc;
load ('ex5data1.mat');
[m,n] = size(X);
theta = [1 ; 1];
J = linearRegCostFunction([ones(m, 1) X], y, theta, 1);
>> J
J = 303.99
Correspondingly, the partial derivative of regularized linear regression’s cost for θj is defined as
In linearRegCostFunction.m, add code to calculate the gradient, re- turning it in the variable grad. When you are finished, the next part of ex5.m will run your gradient function using theta initialized at [1; 1]. You should expect to see a gradient of [-15.30; 598.250].
파라미터 θj에 대한 정규화된 선형 회귀의 비용 함수 J(θ)를 미분하면 다음과 같습니다.
linearRegCostFunction.m 파일에서 기울기를 계산하는 코드를 추가합니다. ex5.m 파일은 theta가 [1;1] 일 때 [-15.30; 598.250]을 표시합니다.
(1) 데이터 업로드 및 기본 변수 설정
clear ; % 옥타브 프로그램에 모든 변수를 제거
close all; % 터미널 이외의 창을 닫음
clc % 터미널 화면을 깨끗이 정리
load ('ex5data1.mat'); % 옥타브 프로그램으로 데이터 업로드
[m,n] = size(X); % 학습 예제의 수와 피처의 수를 정의
(2) 정규화된 선형 회귀에 바이어스 항을 위한 기울기 코드 작성
다음 식을 옥타브 프로그램에서 코드로 작성합니다.
바이어스 항은 정규화하지 않고 그대로 코드 화합니다.
X = [ones(m,1) X]; % 학습 데이터 X에 바이어스 항을 추가
theta = [1;1];
grad = zeros(size(theta)); % 변수 grad를 초기화
grad(1) = 1/m *(X*theta - y)'*X(:,1); % grad를 계산합니다.
(X*theta - y)는 12 X 1차원 벡터이므로 전치하여 1 X 12차원 행 벡터로 전환합니다. X(:,1)은 바이어스 항을 가리키는 12 X1 열 벡터와 계산합니다. 계산 결과는 1차원의 실수입니다.
옥타브 프로그램에서 다음과 같이 입력합니다.
X = [ones(m,1) X];
theta = [1 ; 1];
grad = zeros(size(theta));
>> grad(1) = 1/m *(X*theta - y)'*X(:,1)
grad =
-15.30302
0.00000
(3) 정규화된 선형 회귀에 일반 피처를 위한 기울기 코드 작성
정규화가 필요한 파라미터 theta이 코드를 작성합니다.
grad(2:end) = 1/m *(X*theta - y)'*X(:, 2:end) + lambda/m*theta(2:end);
(X*theta - y)는 12 X 1차원 벡터이므로 전치하여 1 X 12차원 행 벡터로 전환합니다. X(:,2:end)는 12 X1 열 벡터입니다. 두 행렬을 곱하면 1차원 실수입니다. 정규화 항은 theta(1)을 제외한 나머지를 사용하기 위해 theta(2:end)로 나타냅니다.
옥타브 프로그램에 다음과 같이 입력합니다.
>> lambda = 1;
>> grad(2:end) = 1/m *(X*theta - y)'*X(:, 2:end) + lambda/m*theta(2:end)
grad =
-15.303
598.251
문제에서 제시한 grad와 일치합니다.
하지만, submit 하면 다음과 같은 에러가 발생합니다.
이유는 행렬 차원이 맞지 않기 때문입니다. X(:, 2:end)는 12 X1 차원 행렬입니다. 만일 피처 X가 여러 개가 있을 경우에는 12 X (n-1) 차원 행렬입니다. 따라서, 아래 코드에서 X(:,2:end)를 전치하고, (X*theta-y)를 뒤에 배치합니다.
grad(2:end) = 1/m *X(:, 2:end)'*(X*theta - y) + lambda/m*theta(2:end);
저와 같은 오류를 경험할 수 있을 것 같아 기술합니다.
function [J, grad] = linearRegCostFunction(X, y, theta, lambda)
%LINEARREGCOSTFUNCTION 비용과 정규화된 선형 회귀와 비용 함수와 기울기를 계산
%
% [J, grad] = LINEARREGCOSTFUNCTION(X, y, theta, lambda) computes the
% cost of using theta as the parameter for linear regression to fit the
% data points in X and y. Returns the cost in J and the gradient in grad
% 변수 초기화
m = length(y); % 학습 예제의 수
% 반환할 값 초기화
J = 0; % 비용 함수 J의 값
grad = zeros(size(theta)); % 경사 하강법에 의한 경사
% ====================== YOUR CODE HERE ======================
% Instructions: 비용과 정규화된 선형 회귀와 비용 함수와 기울기를 계산
% J와 grad를 설정
%
J = 1/(2*m) *(X*theta - y)'*(X*theta - y) ;
reg = lambda /(2*m) *theta(2:end)'*theta(2:end) ;
J = J + reg;
grad(1) = 1/m *X(:,1)'*(X*theta - y);
grad(2:end) = 1/m *X(:, 2:end)'*(X*theta - y) + lambda/m*theta(2:end);
% ==================================================================
grad = grad(:);
end
Once your cost function and gradient are working correctly, the next part of ex5.m will run the code in trainLinearReg.m to compute the optimal values of θ. This training function uses fmincg to optimize the cost function.
In this part, we set regularization parameter λ to zero. Because our current implementation of linear regression is trying to fit a 2-dimensional θ, regularization will not be incredibly helpful for a θ of such low dimension. In the later parts of the exercise, you will be using polynomial regression with regularization.
Finally, the ex5.m script should also plot the best fit line, resulting in an image similar to Figure 2. The best fit line tells us that the model is not a good fit to the data because the data has a non-linear pattern. While visualizing the best fit as shown is one possible way to debug your learning algorithm, it is not always easy to visualize the data and model. In the next section, you will implement a function to generate learning curves that can help you debug your learning algorithm even if it is not easy to visualize the data.
비용 함수와 기울기를 제대로 계산했다면 ex5.m은 trainLinearReg.m 함수를 호출하여 파라미터 θ의 최적 값을 계산합니다. 데이터 셋을 학습하는 fmincg() 함수를 이용하여 비용을 최적화합니다.
정규화 파라미터 λ를 0으로 설정합니다. 2차원의 파라미터 θ를 데이터에 최적화하려고 하지만, 낮은 차원의 파라미터 벡터 θ에는 큰 도움이 되지 않습니다. 실습 후반부에 정규화화 함께 다항 회귀를 사용합니다.
마지막으로, ex5.m 파일을 실행하여 최적의 가설을 도식화합니다. 그림 2와 유사한 이미지를 만듭니다. 최적의 선은 데이터에 비선형 패턴이 있기 때문에 모델이 데이터에 적합하지 않습니다.. 시각화는 학습 알고리즘을 디버깅하는 한 가지 방법이지만, 시각화가 항상 쉬운 것은 아닙니다.
다음 섹션에서 데이터 시각화가 쉽지 않은 경우에도 학습 알고리즘을 디버깅하는 데 도움을 주는 학습 곡선을 생성하는 함수를 구현합니다.
(1) 데이터 업로드 및 기본 변수 설정
clear ; % 옥타브 프로그램에 모든 변수를 제거
close all; % 터미널 이외의 창을 닫음
clc % 터미널을 깨끗이 정리
load ('ex5data1.mat'); % 옥타브 프로그램으로 데이터 업로드
[m,n] = size(X); % 학습 예제의 수와 피처의 수를 정의
(2) trainLinearReg.m 파일 분석
function [theta] = trainLinearReg(X, y, lambda)
%TRAINLINEARREG 정규화 파라미터 선형 회귀 λ와 데이터 셋에 적합한 선형 회귀를 학습
% [theta] = TRAINLINEARREG (X, y, lambda)
% 학습된 파라미터 theta를 반환
% Theta 초기화
initial_theta = zeros(size(X, 2), 1);
% 비용 함수를 최소화하기 위해 linearRegCostFunction를 호출
costFunction = @(t) linearRegCostFunction(X, y, t, lambda);
% fmincg에서 사용할 옵션 설정
options = optimset('MaxIter', 200, 'GradObj', 'on');
% fmincg 함수는 theta를 최적화
theta = fmincg(costFunction, initial_theta, options);
end
(3) trainLinearReg.m 파일로 최적의 theta를 계산
옥타브 프로그램에 입력하여 theta의 최적 값을 계산합니다.
lambda = 0;
[theta] = trainLinearReg([ones(m, 1) X], y, lambda);
Iteration 14 | Cost: 2.237391e+01
lambda = 1;
[theta] = trainLinearReg([ones(m, 1) X], y, lambda);
Iteration 200 | Cost: 2.237954e+01
(4) 도식화
우선 데이터를 도식화합니다. 데이터 시각화 부분에서 이미 다루었습니다.
plot(X, y, 'rx', 'MarkerSize', 5, 'LineWidth', 1.5);
xlabel('Change in water level (x)');
ylabel('Water flowing out of the dam (y)');
그리고, 가설이자 모델을 그립니다. 12개의 데이터 X와 최적화된 theta를 활용하여 가설 hθ(x)를 계산합니다. hθ(x) = θ^Tx로 가설을 도식화할 수 있습니다. y값이 있을 자리에 hθ(x)를 바로 계산합니다.
hold on;
plot(X, [ones(m, 1) X]*theta, '--', 'LineWidth', 2)
hold off;