파이썬 프로그래밍으로 이해하는 선형회귀 원리
2019-04-27
Data_Engineering_TIL_(20190427)
study program : https://www.fastcampus.co.kr/extension_des
[학습목표]
- Linear Regression 원리 이해
[학습기록]
- 집의 넓이 데이터로 부동산 가격을 예측 하는 Linear Regression을 구현해보자
30평 = 3억 4천만원
50평 = 5억 6천만원
10평 = 1억 4천만원
일때 x평일때 가격은?
- Linear Regression 수식 정립
- Cost Function
어떤가정 h를 세웠을때, 그 가정이 얼마나 틀렸는가를 비용으로 간주하여 수식을 세움
이렇게 정의한 비용을 최소화하는 방향을 파라미터들을 조정하면 좀 더 올바른 가정 h를 가질 수 있다.
이번 예시에서 비용함수는 아래와 같다.
파라미터가 세타0, 세타1인 비용함수이다.
아래 비용함수 수식에서 1/2m은 계산상 편의를 위해, 미분했을때 깔끔하게 떨어지기 때문에 임의로 앞에 붙여준 것이다.
- 그렇다면 J(세타0, 세타1)의 최저점은 어떻게 찾을것인가?
= 오차값을 어떻게 최소화할 것인가?
= cost function 등고선의 골짜기 찾기
- 임의의 지점에서 시작하여 기울기가 낮아지는 지점쪽으로 계속 이동하는 방법을 쓰는데 그 방법을 Gradient Descent 라고 한다.
기울기 = 비용함수의 미분값
- Gradient descent
[실습프리뷰]
위의 회귀분석 예시를 각각의 방법으로 구현해본다.
1) 파이썬 프로그래밍으로 구현
2) numpy를 이용해서 구현
3) scikit-learn을 이용해서 구현
4) spark를 이용해서 구현
1) 파이썬 프로그래밍으로 구현
참고로 변수명 뒤에 _ (언더스코어)가 붙으면 고정된 값임
step1)
x_ = [30, 50, 10]
# 평수
y_ = [34000, 56000, 14000]
# 단위 : 만원
theta0_ = 5000
theta1_ = 1000
def h(x):
return theta1_ * x + theta0_
# h(x) = 1000x + 5000 구현
# 평수 30을 넣었을때 실제값과 약간의 차이가 있는 것을 보임
h(30)
35000
step 2)
이제 하고 싶은 것은 gradient decent 방식을 구현해서 조금 더 나은 오차함수를 출력하고 싶음
def cost_function():
accumulator = 0
m = len(x_)
for i in range(len(x_)):
accumulator += (h(x_[i]) - y_[i]) ** 2
return 1/(2*m) * accumulator
def calculate_grad():
m = len(x_)
grad_theta0 = 1/m * (h(x_[0])-y_[0] + h(x_[1])-y_[1] + h(x_[2])-y_[2])
grad_theta1 = 1/m * (((h(x_[0])-y_[0]) * x_[0]) + ((h(x_[1])-y_[1]) * x_[1]) + \
((h(x_[2])-y_[2]) * x_[2]))
return grad_theta0, grad_theta1
def print_current_cost():
print(cost_function())
alpha = 0.001
for i in range(10000):
grad_theta0, grad_theta1 = calculate_grad()
theta0_ = theta0_ - alpha * grad_theta0
theta1_ = theta1_ - alpha * grad_theta1
print_current_cost()
115094.46476318393
2) numpy를 이용해서 구현
import numpy as np
x_np_ = np.array([30, 50, 10])
y_np_ = np.array([34000, 56000, 14000])
m = x_np_.shape[0] # m = 3
alpha = 0.001
x_np_combined_ = np.concatenate([np.ones(m).reshape(m, 1), x_np_.reshape(m,1)], axis=1)
# x_np_combined_ =
# [[ 1. 30.]
# [ 1. 50.]
# [ 1 .10.]]
theta_ = np.array([5000, 1000]) # theta_ = [5000 1000]
def h_np(x_np_combined_):
return x_np_combined_.dot(theta_)
def cost_function_np():
return 1/(2*m) * np.sum( ( h_np(x_np_combined_) - y_np_ ) ** 2 )
def print_current_cost_np():
print(cost_function_np())
def calculate_grad_np():
grad_theta = 1/m * x_np_combined_.T.dot(h_np(x_np_combined_) - y_np_)
return grad_theta
for i in range(10000):
grad_theta = calculate_grad_np()
theta_ = theta_ - alpha * grad_theta
print_current_cost_np()
115094.46476318393
theta_
array([3353.35983726, 1045.19837837])
3) scikit-learn으로 구현
from sklearn.linear_model import LinearRegression
m = x_np_.shape[0]
x_np_sk_ = np.array([30, 50, 10]).reshape(m,1)
y_np_sk_ = np.array([34000, 56000, 14000]).reshape(m,1)
lr_sklearn = LinearRegression()
model = lr_sklearn.fit(x_np_sk_, y_np_sk_)
model.coef_
array([[1050.]])
model.intercept_
array([3166.66666667])
model.predict([[30]])
array([[34666.66666667]])
4) spark로 구현
import numpy as np
import pandas as pd
x_np_ = np.array([30, 50, 10])
m = x_np_.shape[0]
x_np_sk_ = np.array([30, 50, 10]).reshape(m,1)
y_np_sk_ = np.array([34000, 56000, 14000]).reshape(m,1)
data = np.concatenate([x_np_sk_, y_np_sk_], axis=1)
pd_df = pd.DataFrame(data,columns=['feature1','label'])
pd_df
feature1 | label | |
---|---|---|
0 | 30 | 34000 |
1 | 50 | 56000 |
2 | 10 | 14000 |
import findspark
findspark.init("/home/minman/다운로드/spark-2.4.0-bin-hadoop2.7")
import pyspark
from pyspark.sql import SparkSession
spark = SparkSession.builder.getOrCreate()
df = spark.createDataFrame(pd_df)
df.show()
+--------+-----+
|feature1|label|
+--------+-----+
| 30|34000|
| 50|56000|
| 10|14000|
+--------+-----+
from pyspark.ml.regression import LinearRegression
from pyspark.ml.feature import VectorAssembler
assembler = VectorAssembler(
inputCols=["feature1"],
outputCol="features")
df_feature = assembler.transform(df)
spark_lr = LinearRegression(maxIter=10)
spark_lr_model = spark_lr.fit(df_feature)
# Print the coefficients and intercept for linear regression
print("Coefficients: %s" % str(spark_lr_model.coefficients))
print("Intercept: %s" % str(spark_lr_model.intercept))
Coefficients: [1050.000000000002]
Intercept: 3166.6666666666024