빅데이터 분석 (2주차) 9월14일, 9월16일
파이토치를 이용하여 회귀모형 학습하기
-
(1/5) 회귀모형 소개, 손실 함수
-
(2/5) 경사하강법, 경사하강법을 이용하여 회귀계수 1회 업데이트
-
(3/5) 회귀계수 반복 업데이트
-
(4/5) 학습률
-
(5/5) 사과영상
import torch
import numpy as np
import matplotlib.pyplot as plt
로드맵
- 회귀분석 $\to$ 로지스틱 $\to$ 심층신경망(DNN) $\to$ 합성곱신경망(CNN)
-
model: $y_i= w_0+w_1 x_i +\epsilon_i = 2.5 + 4x_i +\epsilon_i, \quad i=1,2,\dots,n$
- w라는 로테이션을 많이 사용하는 딥러닝
-
model: ${\bf y}={\bf X}{\bf W} +\boldsymbol{\epsilon}$
- ${\bf y}=\begin{bmatrix} y_1 \\ y_2 \\ \dots \\ y_n\end{bmatrix}, \quad {\bf X}=\begin{bmatrix} 1 & x_1 \\ 1 & x_2 \\ \dots \\ 1 & x_n\end{bmatrix}, \quad {\bf W}=\begin{bmatrix} 2.5 \\ 4 \end{bmatrix}, \quad \boldsymbol{\epsilon}= \begin{bmatrix} \epsilon_1 \\ \dots \\ \epsilon_n\end{bmatrix}$
torch.manual_seed(202150754)
n=100
ones=torch.ones(n)
x,_ = torch.randn(n).sort() # 배열하면 tendor,index가 반환됨. 필요한 x만 반환
X = torch.vstack([ones,x]).T
W = torch.tensor([2.5,4])
ϵ = torch.randn(n)*0.5
y = X@W + ϵ #@는 벡터를 곱하라는 뜻..!
ytrue = X@W # 우리가 알고 싶은 것은 평균 직선
plt.plot(x,y,'o') #우리가 관측한 값
plt.plot(x,ytrue,'--') # 우리가 추론하고 싶은 값
-
파란점만 주어졌을때, 주황색 점선을 추론하는것.
-
좀 더 정확하게 말하면 given data로 $\begin{bmatrix} \hat{w}_0 \\ \hat{w}_1 \end{bmatrix}$를 최대한 $\begin{bmatrix} 2.5 \\ 4 \end{bmatrix}$와 비슷하게 찾는것. (2.5와 4는 true의 값)
-
given data : $\big\{(x_i,y_i) \big\}_{i=1}^{n}$
-
parameter: ${\bf W}=\begin{bmatrix} w_0 \\ w_1 \end{bmatrix}$
-
estimated parameter: ${\bf \hat{W}}=\begin{bmatrix} \hat{w}_0 \\ \hat{w}_1 \end{bmatrix}$
plt.plot(x,y,'o') # 그림을 보고 '적당한' 추세를 찾는 과정
-
시도: $(\hat{w}_0,\hat{w}_1)=(-5,10)$을 선택하여 선을 그려보고 적당한지 판단.
- $\hat{y}_i=-5 +10 x_i$ 와 같이 $y_i$의 값을 적합시키겠다는 의미
plt.plot(x,y,'o')
plt.plot(x,-5+10*x,'--') # 그림을 보고 판단해보는 단계
-
벡터 표현으로주황색 추세선을 계산
What = torch.tensor([-5.0,10.0]) # float으로 선언해야 함!!!
plt.plot(x,y,'o')
plt.plot(x,X@What,'--')
-
이론적으로 추론 (회귀 분석)
-
컴퓨터의 반복계산을 이용하여 추론(경사하강법)
(1) initial value: 임의의 선을 그어봄
What = torch.tensor([-5.0,10.0],requires_grad=True)
What
-
처음에는 ${\bf \hat{W}}=\begin{bmatrix} \hat{w}_0 \\ \hat{w}_1 \end{bmatrix}=\begin{bmatrix} -5 \\ 10 \end{bmatrix} $ 를 대입해서 주황색 점선을 적당히 그려보자는 의미
-
끝에 requires_grad=True는 나중에 미분에 사용되기 위함.
yhat=X@What
# yhat을 구하면 단지 X(미분X)*What(미분O) = 미분 옵션이 있는 텐션이 되어버린다.
yhat.data # 미분 옵션이 사라짐.
plt.plot(x,y,'o')
plt.plot(x,yhat.data,'--')
(2) 첫 번째 수정: 추세선의 적당한 정도를 판단하여 적당한 선으로 업데이트
-
'적당한 정도'를 판단하기 위하 장치로서 loss function 도입
$loss=\sum_{i=1}^{n}(y_i-\hat{y}_i)^2=\sum_{i=1}^{n}(y_i-(\hat{w}_0+\hat{w}_1x_i))^2$
$=({\bf y}-{\bf\hat{y}})^\top({\bf y}-{\bf\hat{y}})=({\bf y}-{\bf X}{\bf \hat{W}})^\top({\bf y}-{\bf X}{\bf \hat{W}})$
구현하기 편하게 하기 위해 벡터로 구현
-
loss 함수의 특징
- $y_i \approx \hat{y}_i$ 일수록 loss값이 작다.
- $y_i \approx \hat{y}_i$ 이 되도록 $(\hat{w}_0,\hat{w}_1)$을 잘 찍으면 loss값이 작다.
- (중요) 주황색 점선이
적당할수록
loss값이 작다.
loss = torch.sum((y-yhat)**2) # = (y-yhat)@(y-yhat)
loss
-
$loss(=11003.1260)$을 줄이는, 혹은 없애는 것이 목표 $\to$ 아예 모든 조합 $(\hat{w}_0,\hat{w}_1)$에 대하여 가장 작은 $loss$ 찾기
-
문제의 치환
- 적당해 보이는 주황색 선을 찾자 $\to$ $loss(w_0,w_1)$을 최소로 하는 $(w_0,w_1$의 값을 찾기
-
$loss(w_0,w_1)$를 최소로 하는 $(w_0,w_1)$ 구하는 것으로 수정된 목표
- 단순한 수학문제가 되었다. 마치 $loss(w)=w^2-2w+3$ 을 최소화하는 $w$를 찾으라는 것과 같음.
-
경사하강법, 벡터미분 사용!
경사하강법 아이디어(1차원)
(step 1) 임의의 점을 찍는다.
(step 2) 그 점에서 순간기울기를 구한다. (접선) <-- 미분
(step 3) 순간기울기(= 미분계수)의 부호를 살펴보고 부호와 반대방향으로 움직인다. (순간기울기와 같은 방향으로 움직이면 점점 커질테니까.)
(Tip) 기울기의 절대값 크기와 비례하여 보폭(= 움직이는 정도)을 조절한다.
경사하강법 아이디어(2차원)
(step 1) 임의의 점을 찍는다.
(step 2) 그 점에서 순간기울기를 구한다. (접평면) <-- 편미분
(step 3) 순간기울기(= 여러개의 미분계수)의 부호를 살펴보고 부호와 반대방향으로 각각 움직인다. (순간기울기와 같은 방향으로 움직이면 점점 커질테니까.)
(Tip) 기울기의 절대값 크기와 비례하여 보폭(= 움직이는 정도)을 각각 조절한다.
loss를 줄이도록 $W$를 개선하는 방법
-
$수정값 \leftarrow 원래값 - 기울어진 크기(= 미분계수) \times \alpha$
- 여기에서 $\alpha$는 전체적인 보폭의 크기를 결정한다. 즉, $\alpha$값이 클수록 한 번의 update에 움직이는 양이 크다.
-
${\bf W} \leftarrow {\bf W} - \alpha \times \frac{\partial}{\partial {\bf W}}loss(w_0,w_1)$
-
마이너스의 의미 기울기의 부호를 보고 반대방향으로 움직여라
-
$\frac{\partial}{\partial {\bf W}}loss(w_0,w_1):$ 기울기의 절대값 크기와 비례하여 움직이는 정도를 조정하라. (속도의 조절)
-
$\alpha$의 의미: 전체적인 보폭의 속도를 조절, $\alpha$가 크면 전체적으로 빠르게 움직인다. 다리의 길이로 비유할 수 있다.
-
목표: $loss(=11003.1260)$ 값을 줄이는 것.
-
방법: 경사하강법
-
경사하강법으로 loss를 줄이기 위해서는 $\frac{\partial}{\partial {\bf W}}loss(w_0,w_1)$의 계산이 필요한데, 이를 위해서 벡터미분이 필요하다.
-
requires_grad=True
를 가진 텐서로 미분.
loss=torch.sum((y-yhat)**2)= torch.sum((y-X@What)**2)
# 이었고
What=torch.tensor([-5.0,10.0],requires_grad=True)
# 이므로 결국 What으로 미분하라는 의미.
# 미분한 식이 나오는 것이 아니고,
# 그 식에 (-5.0, 10.0)을 대입한 계수값이 계산됨.
loss.backward() # requires_grad=True를 가진 텐서로 미분하라는 의미
# 단지 미분 계수가 계산되어 있음
# 정확하게 말하면 미분을 활용하여 $(-5,10)$에서의 순간기울기를 구했다는 의미임.
What.grad.data
- 이것이 의미하는 건 $(-5,10)$에서의 순간기울기가 $([-1730.4250, 1485.8135])$ 이라는 의미 (각각 (양수, 음수)로 움직여야 함)
-
직접 계산하여 검증
-
$loss(w_0,w_1)=(y-\hat{y})^\top (y-\hat{y})=(y-XW)^\top (y-XW)$
-
$\frac{\partial}{\partial W}loss(w_0,w_1)=-2X^\top y+2X^\top X W$
-2 * X.T @ y + 2 * X.T @ X @ What # = What.grad.data
alpha=0.001
print('수정 전: ' + str(What.data)) # 미분 옵션 없애기!
print('수정하는 폭: ' + str(-alpha*What.grad.data))
print('수정 후: ' + str(What.data-alpha*What.grad.data))
print('*참값: (2.5,4)')
Wbefore = What.data
Wafter = What.data-alpha*What.grad.data
Wbefore, Wafter
plt.plot(x,y,'o')
plt.plot(x,X@Wbefore,'--b') # 수정 전 파란 점선
plt.plot(x,X@Wafter,'--r') # 수정 후 빨간 점선
plt.title("before: blue // after: red")
(3) Learn (=estimate $\bf\hat{W})$:
What= torch.tensor([-5.0,10.0],requires_grad=True)
alpha=0.001
for epoc in range(30):
What.grad=None
yhat=X@What
loss=torch.sum((y-yhat)**2)
loss.backward() # What으로 미분하는 과정
What.data = What.data-alpha * What.grad.data # 적정한 선으로 Update!
What.data # true 값은 2.5,4
plt.plot(x,y,'o')
plt.plot(x,(X@What.data),'--') # 순수 데이터만 뽑기 위해 .data꼭 붙이기
plt.plot(x,(X@np.array([2.5,4])),'-') # 거의 비슷해서 한 선으로 보임
-
기록 해보기
losses=[] # 기록하고 싶은 것 1
yhats = [] # 기록하고 싶은 것 2
Whats = [] # 기록하고 싶은 것 3
What= torch.tensor([-5.0,10.0],requires_grad=True)
alpha=0.001
for epoc in range(30):
Whats=Whats+[What.data.tolist()] # What을 list화 해서 저장
What.grad=None
yhat=X@What
yhats=yhats+[yhat.data.tolist()]
loss=torch.sum((y-yhat)**2)
losses=losses+[loss.item()]
loss.backward() # What으로 미분하는 과정
What.data = What.data-alpha * What.grad.data # 적정한 선으로 Update!
-
$\hat{y}$ 관찰
plt.plot(x,y,'o')
plt.plot(x,yhats[5],'--') # 5번 업데이트된 추세선
plt.plot(x,y,'o')
plt.plot(x,yhats[10],'--') # 10번 업데이트된 추세선
-
$\hat{\bf{W}}$
losses
plt.plot(losses)
plt.rcParams['figure.figsize'] = (10,4) # 크기
plt.rcParams["animation.html"] = "jshtml" # 애니메이션 나오게 하는 옵션
from matplotlib import animation
fig = plt.figure()
ax1 = fig.add_subplot(1, 2, 1)
ax2 = fig.add_subplot(1, 2, 2, projection='3d')
## ax1: 왼쪽그림
ax1.plot(x,y,'o')
line, = ax1.plot(x,yhats[0])
## ax2: 오른쪽그림
_w0 = np.arange(-6, 11, 0.5) ## 파란색곡면을 그리는 코드 (시작)
_w1 = np.arange(-6, 11, 0.5)
w1,w0 = np.meshgrid(_w1,_w0)
l=w0*0
for i in range(len(_w0)):
for j in range(len(_w1)):
l[i,j]=torch.sum((y-_w0[i]-_w1[j]*x)**2)
ax2.plot_surface(w0, w1, l, rstride=1, cstride=1, color='b',alpha=0.35) ## 파란색곡면을 그리는 코드(끝)
ax2.scatter(2.5,4,torch.sum((y-2.5-4*x)**2),s=200,color='red',marker='*') ## 최소점을 표시하는 코드 (붉은색 별)
ax2.scatter(np.array(Whats)[0,0],np.array(Whats)[0,1],losses[0],color='b') ## 업데이트되는 What을 표시하는 점 (파란색 동그라미)
ax2.azim = 40 ## 3d plot의 view 조절
ax2.dist = 8 ## 3d plot의 view 조절
ax2.elev = 5 ## 3d plot의 view 조절
def animate(epoc):
line.set_ydata(yhats[epoc])
ax2.scatter(np.array(Whats)[epoc,0],np.array(Whats)[epoc,1],losses[epoc],color='grey')
return line
ani = animation.FuncAnimation(fig, animate, frames=30)
plt.close()
ani
(1) $\alpha$가 너무 작다면?$\to$ 비효율적이다.
losses = [] # 기록하고 싶은것 1
yhats = [] # 기록하고 싶은것 2
Whats = [] # 기록하고 싶은것 3
alpha=0.0001
What= torch.tensor([-5.0,10.0],requires_grad=True)
for epoc in range(30):
Whats=Whats+[What.data.tolist()]
What.grad=None
yhat=X@What
yhats=yhats+[yhat.data.tolist()]
loss=torch.sum((y-yhat)**2)
losses = losses + [loss.item()]
loss.backward()
What.data = What.data-alpha * What.grad.data
fig = plt.figure()
ax1 = fig.add_subplot(1, 2, 1)
ax2 = fig.add_subplot(1, 2, 2, projection='3d')
## ax1: 왼쪽그림
ax1.plot(x,y,'o')
line, = ax1.plot(x,yhats[0])
## ax2: 오른쪽그림
_w0 = np.arange(-6, 11, 0.5) ## 파란색곡면을 그리는 코드 (시작)
_w1 = np.arange(-6, 11, 0.5)
w1,w0 = np.meshgrid(_w1,_w0)
l=w0*0
for i in range(len(_w0)):
for j in range(len(_w1)):
l[i,j]=torch.sum((y-_w0[i]-_w1[j]*x)**2)
ax2.plot_surface(w0, w1, l, rstride=1, cstride=1, color='b',alpha=0.35) ## 파란색곡면을 그리는 코드(끝)
ax2.scatter(2.5,4,torch.sum((y-2.5-4*x)**2),s=200,color='red',marker='*') ## 최소점을 표시하는 코드 (붉은색 별)
ax2.scatter(np.array(Whats)[0,0],np.array(Whats)[0,1],losses[0],color='b') ## 업데이트되는 What을 표시하는 점 (파란색 동그라미)
ax2.azim = 40 ## 3d plot의 view 조절
ax2.dist = 8 ## 3d plot의 view 조절
ax2.elev = 5 ## 3d plot의 view 조절
def animate(epoc):
line.set_ydata(yhats[epoc])
ax2.scatter(np.array(Whats)[epoc,0],np.array(Whats)[epoc,1],losses[epoc],color='grey')
return line
ani = animation.FuncAnimation(fig, animate, frames=30)
plt.close()
ani
(1) $\alpha$가 너무 크다면? $\to$ 다른의미에서 비효율적이다 + 위험하다..
losses = [] # 기록하고 싶은것 1
yhats = [] # 기록하고 싶은것 2
Whats = [] # 기록하고 싶은것 3
alpha=0.0083
What= torch.tensor([-5.0,10.0],requires_grad=True)
for epoc in range(30):
Whats=Whats+[What.data.tolist()]
What.grad=None
yhat=X@What
yhats=yhats+[yhat.data.tolist()]
loss=torch.sum((y-yhat)**2)
losses = losses + [loss.item()]
loss.backward()
What.data = What.data-alpha * What.grad.data
fig = plt.figure()
ax1 = fig.add_subplot(1, 2, 1)
ax2 = fig.add_subplot(1, 2, 2, projection='3d')
## ax1: 왼쪽그림
ax1.plot(x,y,'o')
line, = ax1.plot(x,yhats[0])
## ax2: 오른쪽그림
_w0 = np.arange(-6, 11, 0.5) ## 파란색곡면을 그리는 코드 (시작)
_w1 = np.arange(-6, 11, 0.5)
w1,w0 = np.meshgrid(_w1,_w0)
l=w0*0
for i in range(len(_w0)):
for j in range(len(_w1)):
l[i,j]=torch.sum((y-_w0[i]-_w1[j]*x)**2)
ax2.plot_surface(w0, w1, l, rstride=1, cstride=1, color='b',alpha=0.35) ## 파란색곡면을 그리는 코드(끝)
ax2.scatter(2.5,4,torch.sum((y-2.5-4*x)**2),s=200,color='red',marker='*') ## 최소점을 표시하는 코드 (붉은색 별)
ax2.scatter(np.array(Whats)[0,0],np.array(Whats)[0,1],losses[0],color='b') ## 업데이트되는 What을 표시하는 점 (파란색 동그라미)
ax2.azim = 40 ## 3d plot의 view 조절
ax2.dist = 8 ## 3d plot의 view 조절
ax2.elev = 5 ## 3d plot의 view 조절
def animate(epoc):
line.set_ydata(yhats[epoc])
ax2.scatter(np.array(Whats)[epoc,0],np.array(Whats)[epoc,1],losses[epoc],color='grey')
return line
ani = animation.FuncAnimation(fig, animate, frames=30)
plt.close()
ani
(3) $\alpha=0.0085$ 아예 모형을 벗어나버린다.
losses = [] # 기록하고 싶은것 1
yhats = [] # 기록하고 싶은것 2
Whats = [] # 기록하고 싶은것 3
alpha=0.0085
What= torch.tensor([-5.0,10.0],requires_grad=True)
for epoc in range(30):
Whats=Whats+[What.data.tolist()]
What.grad=None
yhat=X@What
yhats=yhats+[yhat.data.tolist()]
loss=torch.sum((y-yhat)**2)
losses = losses + [loss.item()]
loss.backward()
What.data = What.data-alpha * What.grad.data
fig = plt.figure()
ax1 = fig.add_subplot(1, 2, 1)
ax2 = fig.add_subplot(1, 2, 2, projection='3d')
## ax1: 왼쪽그림
ax1.plot(x,y,'o')
line, = ax1.plot(x,yhats[0])
## ax2: 오른쪽그림
_w0 = np.arange(-6, 11, 0.5) ## 파란색곡면을 그리는 코드 (시작)
_w1 = np.arange(-6, 11, 0.5)
w1,w0 = np.meshgrid(_w1,_w0)
l=w0*0
for i in range(len(_w0)):
for j in range(len(_w1)):
l[i,j]=torch.sum((y-_w0[i]-_w1[j]*x)**2)
ax2.plot_surface(w0, w1, l, rstride=1, cstride=1, color='b',alpha=0.35) ## 파란색곡면을 그리는 코드(끝)
ax2.scatter(2.5,4,torch.sum((y-2.5-4*x)**2),s=200,color='red',marker='*') ## 최소점을 표시하는 코드 (붉은색 별)
ax2.scatter(np.array(Whats)[0,0],np.array(Whats)[0,1],losses[0],color='b') ## 업데이트되는 What을 표시하는 점 (파란색 동그라미)
ax2.azim = 40 ## 3d plot의 view 조절
ax2.dist = 8 ## 3d plot의 view 조절
ax2.elev = 5 ## 3d plot의 view 조절
def animate(epoc):
line.set_ydata(yhats[epoc])
ax2.scatter(np.array(Whats)[epoc,0],np.array(Whats)[epoc,1],losses[epoc],color='grey')
return line
ani = animation.FuncAnimation(fig, animate, frames=30)
plt.close()
ani
(4) $\alpha=0.01$
losses = [] # 기록하고 싶은것 1
yhats = [] # 기록하고 싶은것 2
Whats = [] # 기록하고 싶은것 3
alpha=0.01
What= torch.tensor([-5.0,10.0],requires_grad=True)
for epoc in range(30):
Whats=Whats+[What.data.tolist()]
What.grad=None
yhat=X@What
yhats=yhats+[yhat.data.tolist()]
loss=torch.sum((y-yhat)**2)
losses = losses + [loss.item()]
loss.backward()
What.data = What.data-alpha * What.grad.data
fig = plt.figure()
ax1 = fig.add_subplot(1, 2, 1)
ax2 = fig.add_subplot(1, 2, 2, projection='3d')
## ax1: 왼쪽그림
ax1.plot(x,y,'o')
line, = ax1.plot(x,yhats[0])
## ax2: 오른쪽그림
_w0 = np.arange(-6, 11, 0.5) ## 파란색곡면을 그리는 코드 (시작)
_w1 = np.arange(-6, 11, 0.5)
w1,w0 = np.meshgrid(_w1,_w0)
l=w0*0
for i in range(len(_w0)):
for j in range(len(_w1)):
l[i,j]=torch.sum((y-_w0[i]-_w1[j]*x)**2)
ax2.plot_surface(w0, w1, l, rstride=1, cstride=1, color='b',alpha=0.35) ## 파란색곡면을 그리는 코드(끝)
ax2.scatter(2.5,4,torch.sum((y-2.5-4*x)**2),s=200,color='red',marker='*') ## 최소점을 표시하는 코드 (붉은색 별)
ax2.scatter(np.array(Whats)[0,0],np.array(Whats)[0,1],losses[0],color='b') ## 업데이트되는 What을 표시하는 점 (파란색 동그라미)
ax2.azim = 40 ## 3d plot의 view 조절
ax2.dist = 8 ## 3d plot의 view 조절
ax2.elev = 5 ## 3d plot의 view 조절
def animate(epoc):
line.set_ydata(yhats[epoc])
ax2.scatter(np.array(Whats)[epoc,0],np.array(Whats)[epoc,1],losses[epoc],color='grey')
return line
ani = animation.FuncAnimation(fig, animate, frames=30)
plt.close()
ani
(5) $\alpha=0.006$ 숙제
losses = [] # 기록하고 싶은것 1
yhats = [] # 기록하고 싶은것 2
Whats = [] # 기록하고 싶은것 3
alpha=0.006
What= torch.tensor([-5.0,10.0],requires_grad=True)
for epoc in range(30):
Whats=Whats+[What.data.tolist()]
What.grad=None
yhat=X@What
yhats=yhats+[yhat.data.tolist()]
loss=torch.sum((y-yhat)**2)
losses = losses + [loss.item()]
loss.backward()
What.data = What.data-alpha * What.grad.data
fig = plt.figure()
ax1 = fig.add_subplot(1, 2, 1)
ax2 = fig.add_subplot(1, 2, 2, projection='3d')
## ax1: 왼쪽그림
ax1.plot(x,y,'o')
line, = ax1.plot(x,yhats[0])
## ax2: 오른쪽그림
_w0 = np.arange(-6, 11, 0.5) ## 파란색곡면을 그리는 코드 (시작)
_w1 = np.arange(-6, 11, 0.5)
w1,w0 = np.meshgrid(_w1,_w0)
l=w0*0
for i in range(len(_w0)):
for j in range(len(_w1)):
l[i,j]=torch.sum((y-_w0[i]-_w1[j]*x)**2)
ax2.plot_surface(w0, w1, l, rstride=1, cstride=1, color='b',alpha=0.35) ## 파란색곡면을 그리는 코드(끝)
ax2.scatter(2.5,4,torch.sum((y-2.5-4*x)**2),s=200,color='red',marker='*') ## 최소점을 표시하는 코드 (붉은색 별)
ax2.scatter(np.array(Whats)[0,0],np.array(Whats)[0,1],losses[0],color='b') ## 업데이트되는 What을 표시하는 점 (파란색 동그라미)
ax2.azim = 40 ## 3d plot의 view 조절
ax2.dist = 8 ## 3d plot의 view 조절
ax2.elev = 5 ## 3d plot의 view 조절
def animate(epoc):
line.set_ydata(yhats[epoc])
ax2.scatter(np.array(Whats)[epoc,0],np.array(Whats)[epoc,1],losses[epoc],color='grey')
return line
ani = animation.FuncAnimation(fig, animate, frames=30)
plt.close()
ani
-
$\sum_{i=1}^{n}(y_i-\hat{y}_i)^2$ 대신에
- $\frac{1}{n}\sum_{i=1}^{n}(y_i-\hat{y}_i)^2$
- 평균, 이 형태를 많이 쓴다.
- $\frac{1}{2n}\sum_{i=1}^{n}(y_i-\hat{y}_i)^2$
- 미분하면 2 사라짐
중 하나를 사용하여도 상관없다.
-
np.argmin
소개(최소화되는 인덱스 출력해주는 함수)
_a=np.array([1,2,0,2,3,4])
np.argmin(_a) # 인덱스 2(여기서는 0값)번이 최소값
np.argmin(l)
-
무슨 값인지 모름.이런 값이 나오는 이유.
_X=np.array([[1,2,3],[1,-5,-5]])
_X
np.argmin(_X)
l.shape # 34*34=1156개 있음
-
array의 구조가 너무 컴퓨터 위주의 숫자임.. $\to$ np.unravel_index()
함수사용
np.unravel_index(4,_X.shape) # index로 반환해 달라 4 말고
-
응용하면
np.unravel_index(np.argmin(l),l.shape)
_w0[17],_w1[20] # 우리가 바라던 값이 나왔다
-
(2.5,4.0)에서 ;이 최소값을 가지는 것이 맞긴 함
-
그런데 이론적으로 그래야 하는 것은 아님
torch.sum((y-2.5-4.0*x)**2)
XX=np.matrix(X)
yy=np.matrix(y).T # (100,1)로 치환
yy.shape
(XX.T*XX).I * XX.T * yy
torch.sum((y-2.530568-3.9915466*x)**2) # loss값이 더 작아진 모습
- 진짜로 (2.530568,3.9915466) 에서의 로스가 더 작음
-
$n$이 커질수록 (2.530568, 3.9915466) 의 값은 점점 (2.5,4.0)의 값에 가까워 진다.
-
아래의 매트릭스를 관찰하자.
XX
XX[:,1]
- 정상적을 잘 선택되었다.
-
이제 XX에서 첫번째 row를 선택하고 싶다면?
XX[0,:]
-
X에 관심을 가져보자.
-
첫번째 row를 뽑고싶다면?
X[0,:]
-
두번째 col을 뽑고 싶다면?
X[:,1] # 왜 벡터형으로 나올까
-
shape 비교
XX.shape,(XX[0,:]).shape,(XX[:,1]).shape
X.shape,(X[0,:]).shape,(X[:,1]).shape
- row-vec, col-vec의 구분없이 그냥 길이2인 벡터, 길이가 100인 벡터로 고려됨
- row-vec, col-vec의 구분을 하려면 2차원이 필요한데 1차원으로 축소가 되면서 생기는 현상
- 대부분의 경우 별로 문제가 되지 않음.
- 수학적으로는 col-vec, row-vec를 엄밀하게 구분하는 것이 좋지만, 프로그래밍 효율을 생각하면 떄로는 구분이 모호한게 유리할 수도 있다.