반응형

지도학습 : 레벨이 있는 것

비지도 학습 : 레벨이 없는 것 

scikit-learn 에서 최소 제곱법 구현 방법 -> 모델 만드는 것이 가장 쉬운 방법linear_model .

LinearRegression() 모델 만드는 작업을 먼저 해야 한다.

 

결정계수는 데이터전문가들은 수학계산 나올 수 있다.

 

단순선형 회귀 예제 : 결정계수

y = ax + b 처럼 데이터를 만들어 회귀문제를 풀어 보자.

여기서는 y = 3x – 2에 정규분포 난수를 더했을때, 최소 제곱법으로 기울기와 절편을예측해 보자.

# 결정 계수
import numpy as np
import matplotlib.pyplot as plt
from sklearn import linear_model

#학습 데이터
x = np.random.rand(100,1) # 0-1 사이에 난수 100개 생성
x = x * 4 - 2 #x의 범위의 수는 -2 ~ 2

y = 3 * x - 2
#표준 정규분포(평균: 0 , 표준편차 :1)의 난수 추가
y += np.random.rand(100, 1)

#모델 생성
model = linear_model.LinearRegression() # 함수를 가지고 모델 만들어진다

# 모델 학습
model.fit(x, y)

# 회귀계수 , 절편 ,결정개수
print('계수:', model.coef_)
print("절편:",model.intercept_)

r2 = model.score(x,y )
print("결정개수:" , r2) #결정계수 구해준다.

# 산점도 그래프
plt.scatter(x, y , marker="+")
plt.scatter(x, model.predict(x), marker='o')
plt.show()

단순선형 회귀 예제 : 결정계수

y = ax^2 + b 형태의 데이터를 만들어 회귀문제를 풀어 보자.

rand 명령은 0부터 1사이에서 균일한 확률 분포로 실수 난수를 생성한다. 숫자 인수는 생성할 난수의 크기이다. 여러개의 인수를 넣으면 해당 크기를 가진 행렬을 생성한다. 

 

다중 선형 회귀 예제

y = ax1 + bx2 + c 형태의 데이터를 만들어 회귀문제를 풀어 보자.

여기서는 y = 3x1 – 2x2 + 1 에 정규분포 난수를 더했을때, 최소 제곱법으로 회귀계수와 절편을예측해 보자.

# 다중 선형 회귀 분석

import numpy as np
import matplotlib.pyplot as plt
from sklearn import linear_model

# y = 3x_1 - 2x_2 + 1 학습 데이터 생성
x1 = np.random.rand(100, 1) # 0~1까지 난수를 100개 만듞다
x1 = x1 * 4 - 2 # 값의 범위를 -2~2로 변경

x2 = np.random.rand(100, 1) # x2에 대해서도 같게
x2 = x2 * 4 - 2 # 값의 범위를 -2~2로 변경

y =  3 * x1 - 2 * x2 +1
y += np.random.randn(100,1) # 표준정규분포

#x1, x2 데이터를 배열  생성
#배열 형태로 만든다.
x1_x2 = np.c_[x1, x2]
print(x1_x2)

#학습모델 생성
model = linear_model.LinearRegression()

#모델 학습
model.fit(x1_x2, y)

# 회귀계수 , 절편 ,결정개수
print('계수:', model.coef_)
print("절편:", model.intercept_)

r2 = model.score(x1_x2 ,y )
print("결정개수:" , r2) #결정계수 구해준다. 결정개수: 0.940784796428865 예측 성능이 좋다.

#산점도 그리기
y_ = model.predict(x1_x2) # 회귀식으로 예측

plt.subplot(1,2,1) #1행 2열 의 1번째 그래프
plt.scatter(x1,y,marker="+")
plt.scatter(x1, y_ , marker="o")
plt.xlabel('x1')
plt.ylabel('y')

plt.subplot(1, 2, 2) # 1행 2열 배치 , 2번째 subplot
plt.scatter(x2, y, marker='+')
plt.scatter(x2, y_, marker='o')
plt.xlabel('x2')
plt.ylabel('y')

plt.tight_layout()  #자동으로 레이아웃을 설정해주는 함수
plt.show()

 

보스턴 주톡가격 회귀분석

# boston 데이터셋 로드

boston = datasets.load_boston()

보스턴 집값 데이터 :

인덱스 : 506, 컬럼 : 14

target : 키값으로 되여있다.

재일 마지막은 feature_name이 없다.

#보스턴 주택가격 회귀분석

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.datasets import load_boston

# boston 데이터셋 로드
boston = load_boston()

#boston 데이터셋을 이용해서 데이터 생성
bostonDF = pd.DataFrame(boston.data , columns= boston.feature_names)
#잴 마지막에는 컬럼 값이 없기 때문에 13개컬럼만 불러올려고 한다.
print(bostonDF) #[506 rows x 13 columns]

# boston 데이터셋의 target 열(컬럼)은 주택 가격임.
# boston.target을 PRICE 컬럼으로 추가함
bostonDF['PRICE'] = boston.target
print('boston 데이터 형태: ' ,bostonDF.shape ) #boston데이터 형태(506,14)
print(bostonDF.head())
print(bostonDF)

#boston데이터셋을 boston.csv파일로 저장
bostonDF.to_csv('boston.csv', encoding='utf-8')

# 다음의 각 컬럼 RM, ZN, INDUS, NOX, AGE, PTRATIO, LSTAT, RAD 의 총 8개의 컬럼에
# 대해서 값이 증가핛수록 PRICE에 어떤 영향을 미치는지 분석하고 시각화를 해보자

# 2개의 행과 4개의 열을 가짂 subplots 로 시각화, axs는 4x2개의 ax를 가짐
fig, axs = plt.subplots(figsize=(16,8) , ncols=4, nrows=2)#2행 4열 구조로
Im_features = ['RM', 'ZN', 'INDUS', 'NOX', 'AGE', 'PTRATIO', 'LSTAT', 'RAD']
for i , feature in enumerate(Im_features):
    row = int(i/4)
    col = i % 4

    sns.regplot(x = feature, y ='PRICE', data = bostonDF, ax= axs[row][col]) # ax= axs[row][col]그래프

plt.show()

# RM(방개수)와 LSTAT(하위 계층의 비율)이 PRICE에 영향도가 가장 두드러지게 나타남.
# 1. RM(방개수)은 양 방향의 선형성(Positive Linearity)이 가장 크다.
# 방의 개수가 많을수록 가격이 증가하는 모습을 확연히 보여준다.
# 2. LSTAT(하위 계층의 비율)는 음 방향의 선형성(Negative Linearity)이 가장 크다.
# 하위 계층의 비율이 낮을수록 PRICE 가 증가하는 모습을 확연히 보여준다.

#전체 데이트를 나누어서 처리 7:3 정도 나누어서 처리한다.
#random_state= 156 seed와 같은 역할

#overfitting을 줄이기 위한 한가지 방법은 학습데이터와 test데이터를 줄이는 것
# LinearRegression 클래스를 이용해서 보스턴 주택 가격의 회귀 모델을 만들어 보자
# train_test_split()을 이용해 학습과 테스트 데이터셋을 분리해서 학습과 예측을 수행핚다.
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score

#x_Data price제외한 데이터
#x_test price 만 있는 데이터
# train은 학습을 할때 사용하는 것
#test는 예측 할때 사용한다. 얼마나 예측 잘 했는지
#일차의 교차검정
#overftting은 트래인 데이터가 잘 되는 것
#axis = 1 이면 컬럼 0이면 행
#x_data 13개 컬럼 -> train을 하는 것이 다.
#train_test_split -> (13개 정보 , price, 데이터 크기를 30%로 할당 테스트 데이터 뒤쪽에 있는 데이터, )
#학습을 시키기 위해서 학습 데이터 x_train ,  y_train 13개 컬럼이 학습에 얼마나 영향을 주는지
#예측을 할때나 평가를 할 때는 test데이터 가지고 한다.
#모듈을 얼마나 잘했는지 test데이터를 한다.
#overfitting 줄이기 위해서

y_target = bostonDF['PRICE']

#데이터프레임에서 price 컬럼을 삭제한다.
x_data = bostonDF.drop(['PRICE'], axis= 1, inplace=False) #특정 컬럼을 삭제 할 때 사용
#inplace true로 하면 none이 return한다. false이야만 값 리턴한다.
#13개 컬럼정보

#train_data 학습을 하기 위해서
#test_data 예측하거나 모델을 평가할 때 하는 데이터
#random_state seed하고 같다 실행할 때 마다 같은 결과가 나온다.
x_train, x_test, y_train, y_test = train_test_split(x_data, y_target, test_size=0.3, random_state=156)
#print('x_train:' , x_train) #학습용 데이터
#print('x_test:' , x_test) #검증을 하거나 예측을 할떄 사용
#print('y_train:' , y_train)
#print('y_test:' , y_test)

#from sklearn.linear_model import LinearRegression
# 선형회귀 모델생성/ 모델학습 / 모델예측 / 모델평가 수행
model = LinearRegression() # 모델 생성

#모델 학습
model.fit(x_train, y_train) # 13개 컬럼이 price에 어떤 영향을 주는지

#모델 예측- 학습된 데이터로 예측
y_predict = model.predict(x_test) #테스트 값가지고 해야 한다. 예측값
#13개 컬럼이 들어갔을 때 가격에 얼마나 영향 주는지 모델 학습이 되여서 예측이 가능하다.
#아니면 신뢰도가 떨어진다.
print('y_predict:' ,y_predict) #13개 컬럼 30%가지고 예축한다.

#모델 평가
#r2_score 메트릭스로 구하기 때문에  r2_score(실제데이터, 예측데이터 )
print('결정계수:',r2_score(y_test, y_predict))
# Variance score : 0.757

# LinearRegression 으로 생성핚 주택가격 모델의 회귀계수(coefficients)와
# 절편(intercept)을 구해보자
# 회귀계수는 LinearRegression 객체의 coef_ 속성으로 구핛수 있고,
# 절편은 LinearRegression 객체의 intercept_ 속성으로 구핛수 있다.
print('회귀계수:',model.coef_)
print('절편:', model.intercept_)

#회귀계수를 큰 값 순으로 정렬하기 위해서 Series로 생성함.
#series데이터 는 1차원
#round함수 반올림
coff = pd.Series(data = np.round(model.coef_,1) ,index= x_data.columns)
print(coff.sort_values(ascending=False)) # ascending=False 내림차순 정렬

# RM 3.4 # 방개수 기울기가 가장 큰 것으로 나온다.
# CHAS 3.0
# RAD 0.4
# ZN 0.1
# B 0.0
# TAX -0.0
# AGE 0.0
# INDUS 0.0
# CRIM -0.1
# LSTAT -0.6
# PTRATIO -0.9
# DIS -1.7
# NOX -19.8 # 일산화질소 농도

 양의 상관관계 음의 상관관계

양의 상관관계 대각선으로 되여 있고

음의 상관관계는 반대로 되여 있다.

 

enumerate 함수

·       리스트가 있는 경우 순서와 리스트의 값을 전달하는 기능을 가집니다.

·       enumerate는 “열거하다”라는 뜻입니다.

·       이 함수는 순서가 있는 자료형(list, set, tuple, dictionary, string)을 입력으로 받아 인덱스 값을 포함하는 enumerate 객체를 리턴합니다.

·       보통 enumerate 함수는 for문과 함께 자주 사용됩니다.

 

기울기가 작아도 골고루 분포 되여 있어야 영향이 있는지 볼 수 있다.

기울기가 양의 방향과 음의 방향 이있다.

절대적으로 가격에 영향을 주는지 아닌지 결정 못한다.

 

 

학습데이터 실제데이터 분할 될때는 y_test, predict로 한다.

기울기 하고 분포(실제데이터) 같이 봐야 한다.

일정한 방향으로 되여있기 때문에 회기선과 실제데이터 사이에 관련이 있다. 분포 같이 보고 확인 해야 한다. 

 

단순회귀분석 예제

UCI(University of California, Irvine) 자동차 연비 데이터셋으로단순회귀분석을 해보자

Step1. 데이터 준비

Step2. 데이터 탐색

Step3. 분석에 홗용핛 속성(feature 또는 variable) 선택 및 그래프 그리기독립변수 : weight(중량), 종속변수 : mpg(연비)

Step4. 훈련 데이터 / 검증 데이터 분할

Step5. 모델 학습 및 모델 검증

 

# 기본 라이브러리 불러오기
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

#자동차 정보 파일 읽어와서 데이터프레임 생성
df = pd.read_csv('auto-mpg.csv', header=None)
#print(df) # 컬럼 번호로 출력 ( 0 ~ 8 ) [398 rows x 9 columns]

#컬럼명 설정
df.columns = ['mpg','cylinders','displacement','horsepower','weight','acceleration','model year','origin','name']
#mpg 연비
print(df.head()) #앞에서 5개의 데이터 출력

#한줄에  10개의 컬럼 출력
pd.set_option('display.max_columns', 10)
print(df.head()) #앞에서 5개의 데이터 출력
 
-=>  
# IPython 디스플레이 설정 - 출력핛 열의 개수 늘리기
pd.set_option('display.max_columns', 10)

Step2. 데이터 탐색

# 데이터 자료형 확인
# 데이터 자료형 확인
print(df.info()) # horsepower 열의 자료형 object(문자형)

#horsepower 열의 자료형 변경 (문자형 ->실수형)
#horsepower는 문자형으로 되여있다. 문자형으로 되여있으면 통계예약이 안된다.

# horsepower 열의 자료형 변경 (문자형 ->실수형)

#통계요약 정보 확인
print(df.describe())
#통계요약 을 할수 있느 값만 나타난다.
#두개 컬럼 문자열이여서 결과가 출력이 안된다.  horsepower,name


# horsepower 열의 고유값 확인
print(df['horsepower'].unique()) #숫자는 그대로 나오고 문자는 따옴표로 해서 나온다.
# '?' 값이 없는 것 이것을 결측치로 바꿔주는 작업을 해야 한다. 이런 값은 숫자로 못 바꿘다.
# 이것을 없애주는 작업을 수행해야 한다.
# horserpower 컬럼의 '?'을 np.nan으로 변경
df['horsepower'].replace('?',np.nan, inplace=True)
#horsepower 컬럼을 문자형여르 실수형으로 변환
df['horsepower'] = df['horsepower'].astype('float')

#변경 정보 확인: 통계 요약 정보 출력
# 숫자열이 않이면 안나온다. 숫자형으로 변경해서 나온다.
print(df.describe()) # horsepower이 나온다.

Step3. 분석에 홗용핛 속성(feature 또는 variable) 선택 및 그래프 그리기

#분석에 홗용핛 열(속성)을 선택 (연비, 실린더, 출력, 중량)
ndf = df[['mpg', 'cylinders', 'horsepower', 'weight']]
print(ndf.head()) # 앞에서 5개의 데이터 출력
# 분석에 필요한 4가지 컬럼으로

# 독립변수(x) weight(중량)와 종속 변수(y) mpg(연비) 갂의 선형관계를 산점도 그래프로 확인
# 1.matplotlib으로 산점도 그리기
# 1.pandas로 산점도 그리기
ndf.plot(kind ='scatter' , x = 'weight' , y ='mpg', c='coral', figsize=(10,5))

plt.show()

#2. seaborn 산점도 그리기
fig = plt.figure(figsize=(10, 5))
ax1 = fig.add_subplot(
1,2,1)
ax2 = fig.add_subplot(
1,2,2)
sns.regplot(
x ='weight', y = 'mpg', data=ndf, ax = ax1 , fit_reg=True) #회귀선 표시
sns.regplot(x ='weight', y = 'mpg', data=ndf, ax = ax2 , fit_reg=False) #회귀선 미표시
plt.show()

# 3.seaborn 조인트 그래프 - 산점도, 히스토그램
sns.jointplot(x = 'weight' , y = 'mpg', data=ndf) #회귀선 없음
sns.jointplot(x = 'weight' , y = 'mpg', data=ndf , kind='reg')
plt.show()

# 4.seaborn pariplot으로 두 변수 갂의 모두 경우의 수 그리기
sns.pairplot(ndf)
plt.show()

Step4. 훈련 데이터 / 검증 데이터 분할

 

# 속성(변수) 선택
x=ndf[['weight']] # 독립 변수 : x
y=ndf['mpg'] # 종속 변수 : y
# train data 와 test data로 분핛(7:3 비율)
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(x, # 독립 변수
y, # 종속 변수
test_size=0.3, # 검증 30%
random_state=10) # 랜덤 추출 값
print('train data 개수: ', len(x_train))
print('test data 개수: ', len(x_test))

Step5. 모델 학습 및 모델 검증

# train 데이터 가지고 학습을 시킨다.
#모듈 import
from sklearn.linear_model import LinearRegression

#모델 생성
model = LinearRegression()

#train data를 이용해서 모듈 학습
model.fit(x_train, y_train) #학습을 하는 데이터

#결정계수
r_square = model.score(x_test, y_test)#모듈로 하는것
print('결정계수:', r_square) #결정계수 0.6893638093152089

#회귀계수 ,절편
print('회귀계수:', model.coef_)
print('절편', model.intercept_)

#예측값과 실제값을 그래프로 출력
y_predict = model.predict(x_test) #예측값
# x는 전체 데이터이고 x_test 테스트 를 하기 위한 weigth정보 
#30%에 대한 연비 정보

plt.figure(figsize=(10, 5))
ax1 = sns.distplot(y_test , hist=False, label='y') #실제값 출력
ax2 = sns.distplot(y_predict, hist=False , label='y_hat') #예측값
plt.show()

독립변수 하나가 있는 것을 단순 회귀분석이라고 한다.

오차가 크다 라는 것을 알 수 있다.

weight가 높을때 연비 가 낮다.

상대적이다.실제데이터는 왼쪽으로 되여있고 예측 데이터는 오르쪽으로 되여있다.

 

다항회귀분석(Polynomial Regression)

#다항회귀분석

#Step1. 데이터 준비
# 기본 라이브러리 불러오기
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

# CSV 파일을 읽어와서 데이터프레임으로 변홖
df = pd.read_csv('auto-mpg.csv', header=None)

# 열 이름 지정
df.columns = ['mpg','cylinders','displacement','horsepower','weight', 'acceleration','model year','origin','name']

#Step2. 데이터 탐색
# horsepower 열의 자료형 변경 (문자형 ->실수형)
df['horsepower'].replace('?', np.nan, inplace=True) # '?'을 np.nan으로 변경

df['horsepower'] = df['horsepower'].astype('float') # 문자형을 실수형으로 변홖

print(df.describe()) # 데이터 통계 요약정보 확인
print('\n')

#Step3. 분석에 홗용핛 속성(feature 또는 variable) 선택
# 분석에 홗용핛 열(속성)을 선택 (연비, 실린더, 출력, 중량)
ndf = df[['mpg', 'cylinders', 'horsepower', 'weight']]
print(ndf.head())

#Step4. 훈련 데이터 / 검증 데이터 분핛
# ndf 데이터를 train data 와 test data로 구분(7:3 비율)
x=ndf[['weight']] #독립 변수 x : weight(중랼)
y=ndf['mpg'] #종속 변수 y : mpg(연비)
#x, y가 분할된 데이터이다.

#train data 와 test data로 구분(7:3 비율)
from sklearn.model_selection import train_test_split
x_train, x_test, y_train , y_test = train_test_split(x, y , test_size=0.3, random_state=10)

print('훈련 데이터: ', x_train.shape) # 훈련 데이터: (274, 1)
print('검증 데이터: ', x_test.shape) # 검증 데이터: (118, 1)
print('\n')

#Step5. 모델 학습 및 모델 검증
# PolynomialFeatures 다항식 degree = 2 2차형 3으로 하면 3차형

#모듈 불러오기
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import PolynomialFeatures

poly = PolynomialFeatures(degree=2) # 2차항 적용
x_train_poly = poly.fit_transform(x_train) # x_train 데이터를 2차항으로 변홖
print(x_train_poly) # x_train의 1개의 열이 x_train_poly 에서는 3개의 열로 늘어난다.

print('원래데이터:' ,x_train.shape) #원래데이터: (278, 1)
print('2차항 변환 데이터:' ,x_train_poly.shape) #2차항 변환 데이터: (278, 3)
# x_train의 1개의 열이 x_train_poly 에서는 3개의 열로 늘어난다.

#모델 생성
model = LinearRegression()

#train data를 이용해서 모델 학습
model.fit(x_train_poly, y_train)

#결정 계수
x_test_poly = poly.fit_transform(x_test) #x_test데이터를 제곱항 형태로 변환
r_square = model.score(x_test_poly, y_test) #실제데이터
#연비는 종속변수이기 때문에 안 변한다.
#일차항이던 2차항이던 바꾸지 않는다.

print("결정계수 :" , r_square)

# train data의 산점도와 test data로 예측핚 회귀선을 그래프로 출력
#쳬측하기
y_hat_predict = model.predict(x_test_poly) #테스트 데이터 가지고 예측 한다.

# train data의 산점도와 test data로 예측핚 회귀선을 그래프로 출력
fig = plt.figure(figsize=(10, 5)) # 그래프 크기 설정
ax = fig.add_subplot(1, 1, 1)
ax.plot(x_train, y_train, 'o' , label='Train Data') # train data의 산점도
ax.plot(x_test, y_hat_predict, 'r+', label='Predicted Value') # 모델이 학습핚 회귀선
ax.legend(loc='best') # 범례 설정 label를 설정하며 범례가 설정된다.
plt.xlabel('weight') # x축 라벨
plt.ylabel('mpg') # y축 라벨
plt.show()
plt.close()

 

다항 회귀분석이 단순회귀분석보다 정확하게 나온것을 확인할 수 있습니다.

# 실제값 y와 예측값 y_hat 의 분포 차이 비교
# 모델에 전체 x데이터를 입력하여 예측핚 값 y_hat을 실제 값 y와 비교
x_poly = poly.fit_transform(x) # x데이터를 2차항으로 변환
#x는 weight 정보가 되여있습니다.
y_hat = model.predict(x_poly) #예측 한다.

# displot() 함수 : 히스토그램 + 커널밀도함수
plt.figure(figsize=(10, 5)) # 그래프 크기 설정
ax1 = sns.distplot(y, hist=False, label="y") # 실제값
ax2 = sns.distplot(y_hat, hist=False, label="y_hat", ax=ax1) # 예측값
#ax=ax1 그래프가 결합이 되서 나타난다. 
plt.show()

제곱항 degree = 2

반응형

'Study > 머신러닝' 카테고리의 다른 글

머신러닝-6  (0) 2020.11.19
머신러닝-5  (0) 2020.11.19
머신러닝-4  (0) 2020.11.17
머신러닝-2  (0) 2020.11.14
머신러닝-1  (0) 2020.11.14

+ Recent posts