
train set으로 나온 예측이 일반적으로 test set으로 한 예측보다 좋은 값이 나온다. 이 차이가 적을수록 좋은 모델.
#데이터
import numpy as np
perch_length = np.array([25.4, 26.3, 26.5, 29.0, 29.0, 29.7, 29.7, 30.0, 30.0, 30.7, 31.0, 31.0,
31.5, 32.0, 32.0, 32.0, 33.0, 33.0, 33.5, 33.5, 34.0, 34.0, 34.5, 35.0,
35.0, 35.0, 35.0, 36.0, 36.0, 37.0, 38.5, 38.5, 39.5, 41.0, 41.0, 9.8,
10.5, 10.6, 11.0, 11.2, 11.3, 11.8, 11.8, 12.0, 12.2, 12.4, 13.0, 14.3, 15.0])
perch_weight = np.array([242.0, 290.0, 340.0, 363.0, 430.0, 450.0, 500.0, 390.0, 450.0, 500.0, 475.0, 500.0,
500.0, 340.0, 600.0, 600.0, 700.0, 700.0, 610.0, 650.0, 575.0, 685.0, 620.0, 680.0,
700.0, 725.0, 720.0, 714.0, 850.0, 1000.0, 920.0, 955.0, 925.0, 975.0, 950.0, 6.7,
7.5, 7.0, 9.7, 9.8, 8.7, 10.0, 9.9, 9.8, 12.2, 13.4, 12.2, 19.7, 19.9])
#데이터 시각화해서 파악
import matplotlib.pyplot as plt
plt.scatter(perch_length, perch_weight)
plt.xlabel('length')
plt.ylabel('weight')
plt.show()
#데이터 나누기
from sklearn.model_selection import train_test_split
train_input, test_input, train_target, test_target = train_test_split(
perch_length, perch_weight, random_state=42)
train_input = train_input.reshape(-1, 1)
test_input = test_input.reshape(-1, 1)



train_test_split에 넣은 데이터가 각각 perch_length(X), perch_weight(y)로 길이로 무게를 예측할 건데, 각각 1차원 numpy 배열이다. => 따라서 split한 결과도 1차원 배열로 나온다. test_size=0.2: 테스트셋의 사이즈를 지정. 남은 게 train_set.shuffle=True: 데이터를 분할하기 전에 무작위로 섞어서, 순서에 의존하지 않도록 한다. stratify=label: 분할된 데이터셋이 원본 데이터셋의 클래스 비율을 유지하도록 한다. 클래스간 불균형이 클 때 중요. .rehspae(-1, 1): reshape는 넘파이 배열의 엘리먼트를 보고, 원하는 모습으로 shape를 바꾼다. -1은 자동으로 맞춘다는 뜻. 즉, 열은 1열, 행은 그거에 맞춰서, 2차원 모양으로 만든다. from sklearn.neighbors import KNeighborsRegressor
knr = KNeighborsRegressor()
knr.fit(train_input, train_target)
knr.score(test_input, test_target)
from sklearn.metrics import mean_absolute_error
test_prediction = knr.predict(test_input)
# 테스트 세트에 대한 평균 절댓값 오차를 계산
mae = mean_absolute_error(test_target, test_prediction)
knr.score()로 나오는 값은 . 아래 수식에서 y는 실제값, y_hat은 예측값, y_bar는 관측값 평균. 즉, 1은 모델이 완벽하게 예측, 0은 평균값만큼 예측, 0보다 작으면 그냥 평균값 넣은 것보다 나쁜 예측.
mean_absolute_error(y_tue, y_pred): 예측값과 실제값 사이의 절대 오차 평균을 계산해서, 회귀 모델의 예측 성능을 평가. 
knr.score(train_input, train_target)알 때 0.977 => 이걸 knr.n_neighbors=3으로 바꾸면 -.988 즉, 과소적합이 좀 잡혔다knr = KNeighborsRegressor()
# 5에서 45까지 x 좌표를 만듭니다
x = np.arange(5, 45).reshape(-1, 1)
# n = 1, 5, 10일 때 예측 결과를 그래프로
for n in [1, 5, 10]:
knr.n_neighbors = n
knr.fit(train_input, train_target)
# 지정한 범위 x에 대한 예측 구하기
prediction = knr.predict(x)
# 훈련 세트와 예측 결과 그래프 그리기
plt.scatter(train_input, train_target)
plt.plot(x, prediction)
plt.title('n_neighbors = {}'.format(n))
plt.xlabel('length')
plt.ylabel('weight')
plt.show()

perch_length = np.array(
[8.4, 13.7, 15.0, 16.2, 17.4, 18.0, 18.7, 19.0, 19.6, 20.0,
21.0, 21.0, 21.0, 21.3, 22.0, 22.0, 22.0, 22.0, 22.0, 22.5,
22.5, 22.7, 23.0, 23.5, 24.0, 24.0, 24.6, 25.0, 25.6, 26.5,
27.3, 27.5, 27.5, 27.5, 28.0, 28.7, 30.0, 32.8, 34.5, 35.0,
36.5, 36.0, 37.0, 37.0, 39.0, 39.0, 39.0, 40.0, 40.0, 40.0,
40.0, 42.0, 43.0, 43.0, 43.5, 44.0]
)
perch_weight = np.array(
[5.9, 32.0, 40.0, 51.5, 70.0, 100.0, 78.0, 80.0, 85.0, 85.0,
110.0, 115.0, 125.0, 130.0, 120.0, 120.0, 130.0, 135.0, 110.0,
130.0, 150.0, 145.0, 150.0, 170.0, 225.0, 145.0, 188.0, 180.0,
197.0, 218.0, 300.0, 260.0, 265.0, 250.0, 250.0, 300.0, 320.0,
514.0, 556.0, 840.0, 685.0, 700.0, 700.0, 690.0, 900.0, 650.0,
820.0, 850.0, 900.0, 1015.0, 820.0, 1100.0, 1000.0, 1100.0,
1000.0, 1000.0]
)
train_input, test_input, train_target, test_target = train_test_split(
perch_length, perch_weight, random_state=42)
train_input = train_input.reshape(-1, 1)
test_input = test_input.reshape(-1, 1)
from sklearn.neighbors import KNeighborsRegressor
knr = KNeighborsRegressor(n_neighbors = 3)
knr.fit(train_input, train_target)
knr.predict([[50]])
distances, indexes = knr.kneighbors([[50]])
plt.scatter(train_input, train_target)
plt.scatter(train_input[indexes], train_target[indexes],
marker = 'D')
#50cm 농어의 예측치(knr.predict([[50]])이 1033
plt.scatter(50, 1033, marker = '^')
plt.xlabel('length')
plt.ylabel('weight')
plt.show()

#train_target 근처 값들의 평균이 1033
print(np.mean(train_target[indexes]))
print(knr.predict([[100]]))
#이상하다. 50도 1033, 100도 1033
#100으로 해보면, 그래도 똑같다. 즉, 잘못 됐다 모델이
distances, indexes = knr.kneighbors([[100]])
plt.scatter(train_input, train_target)
plt.scatter(train_input[indexes], train_target[indexes],
marker = 'D')
#50cm 농어의 예측치
plt.scatter(100, 1033, marker = '^')
plt.xlabel('length')
plt.ylabel('weight')
plt.show()

from sklearn.linear_model import LinearRegression
lr = LinearRegression()
lr.fit(train_input, train_target)
print(lr.predict([[50]]))
#기울기(계수), 절편
print(lr.coef_, lr.intercept_)
plt.scatter(train_input, train_target)
#15에서 50까지 1차 방정식(y=ax+b) 그래프를 그립니다
plt.plot([15, 50], [15*lr.coef_ + lr.intercept_,
50*lr.coef_ + lr.intercept_])
#50cm 농어 데이터
plt.scatter(50, 1241.8, marker='^')
plt.xlabel('length')
plt.ylabel('weight')
plt.show()
print(lr.score(train_input, train_target))
print(lr.score(test_input, test_target))
LinearRegression(): LinearRegression 객체 생성lr.coef_, lr.intercept_: 각각 이 모델의 계수(기울기)와 절편.
#[제곱값, 원래값]의 배열로
train_poly = np.column_stack((train_input ** 2, train_input))
test_poly = np.column_stack((test_input ** 2, test_input))
lr = LinearRegression()
lr.fit(train_poly, train_target)
print(lr.predict([[50**2, 50]]))
print(lr.coef_, lr.intercept_)
#15에서 49까지 정수 배열
point = np.arange(15, 50)
plt.scatter(train_input, train_target)
plt.plot(point, 1.01 * point ** 2 - 21.6*point + 116.05)
#50cm의 농어 데이터
plt.scatter([50], [1574], marker='^')
plt.xlabel('length')
plt.ylabel('weight')
plt.show()




#온라인에 올린 데이터 불러오기
df = pd.read_csv('https://bit.ly/perch_csv_data')
perch_full = df.to_numpy()
#length, weight, width
train_input, test_input, train_target, test_target = train_test_split(
perch_full, perch_weight, random_state=42)
#preprocessing은 전처리기
from sklearn.preprocessing import PolynomialFeatures
#실험용
poly = PolynomialFeatures()
poly.fit([[2, 3, 4.5]])
print(poly.transform([[2, 3, 4.5]]))
#실험용
poly = PolynomialFeatures()
poly.fit([[2, 3]])
print(poly.transform([[2, 3]])
#3개의 특성 => 9개가 된다
poly = PolynomialFeatures(include_bias = False)
poly.fit(train_input)
train_poly = poly.transform(train_input)
poly.get_feature_names_out()
PolynomialFeatures(): 원본 데이터의 특성을 사용해, 지정된 차수까지의 모든 다항식 조합을 생성하는 인스턴스. 여기서 별도의 차수(degree) 지정하지 않으면 기본값인 2차 다항식 특성 생성. 3차로 하면 3차 다항식 특성 생성. include_bias=False: 아래에 있는 다항식의 절편 1을 생략. poly.fit([[2, 3]]): 입력 데이터에 대한 변환 준비. [2, 3]이라는 2차원 배열을 입력으로 사용. poly.transform([[2, 3]]): fit 메서드에서 학습된 변환을 실제 데이터에 적용하여 다항 특성을 생성. => poly.fit과 poly.transform에 들어간 데이터가 다를 경우, transform의 다항식 특성 조합을 생성한다. poly.transform(train_input): 여기서 train_input은 (42, 3)으로 총 3개의 특성을 갖고 있다. => 이게 9개로 1을 제외하고 9개로 늘어난다. 원본값, 원본값의 제곱, 원본값의 조합으로. poly.get_feature_names_out(): PolynomialFeatures 변환기를 사용해 생성된 다항식 특성 이름을 반환. from sklearn.linear_model import LinearRegression
lr = LinearRegression()
lr.fit(train_poly, train_target)
print(lr.score(train_poly, train_target))
print(lr.score(test_poly, test_target))
#degree=5로 해서 변수를 55개로 늘렸다
poly = PolynomialFeatures(degree=5, include_bias = False)
poly.fit(train_input)
train_poly = poly.transform(train_input)
test_poly = poly.transform(test_input)
lr.fit(train_poly, train_target)
print(lr.score(train_poly, train_target))
print(lr.score(test_poly, test_target))
from sklearn.preprocessing import StandardScaler
ss = StandardScaler()
ss.fit(train_poly)
train_scaled = ss.transform(train_poly)
test_scaled = ss.transform(test_poly)
StandScaler: 데이터 표준화(Standardization)을 위한 전처리 기능. 각 특성(변수)의 평균을 0으로, 표준편차를 1로 조정해서 데이터의 스케일을 통일하는 인스턴스 생성.
ss.fit(): 데이터의 평균과 표준편차를 계산. ss.transform(): 표준화. 
from sklearn.linear_model import Ridge
ridge = Ridge()
ridge.fit(train_scaled, train_target)
print(ridge.score(train_scaled, train_target))
print(ridge.score(test_scaled, test_target))
Ridge()는 Ridge Regression 하는 객체. fit하고, score 매기고, 똑같다.alpha=를 넣을 수 있는데, 이게 위의 하이퍼파라미터값. 1이 기본. #alpha 값을 10으 ㅣ배수로. 이걸로 최적의 하이퍼 파라미터 찾기
alpha_list = [0.001, 0.01, 0.1, 1, 10, 100]
for alpha in alpha_list:
ridge = Ridge(alpha=alpha)
ridge.fit(train_scaled, train_target)
train_score.append(ridge.score(train_scaled, train_target))
test_score.append(ridge.score(test_scaled, test_target))
plt.plot(np.log10(alpha_list), train_score, label='Train Score')
plt.plot(np.log10(alpha_list), test_score, label='Test Score')
plt.xlabel('log10(alpha)')
plt.ylabel('R^2')
plt.legend()
plt.show()


from sklearn.linear_model import Lasso
lasso = Lasso()
lasso.fit(train_scaled, train_target)
print(lasso.score(train_scaled, train_target))
print(lasso.score(test_scaled, test_target))
train_score = []
test_score = []
alpha_list = [0.001, 0.01, 0.1, 1, 10, 100]
for alpha in alpha_list:
lasso = Lasso(alpha=alpha, max_iter=10000)
lasso.fit(train_scaled, train_target)
train_score.append(lasso.score(train_scaled, train_target))
test_score.append(lasso.score(test_scaled, test_target))
plt.plot(np.log10(alpha_list), train_score, label='Train Score')
plt.plot(np.log10(alpha_list), test_score, label='Test Score')
plt.xlabel('alpha')
plt.ylabel('R^2')
plt.legend()
plt.show()
Lasso()라는 객체를 만들어서 사용. alpha=의 디폴트 값이 1000.max_iter=10000np.sum(lasso.coef_==0))이 40. 위의 55개까지 속성값을 늘린 걸 사용했다. 그런데 40개 밖에 사용되지 않았다. 이유는?