k-NN 알고리즘
k-NN은 새로운 데이터가 들어왔을 때, 그 주변에 있는 가까운 데이터(k개)를 참고하여 값을 예측하는 방법.
'비슷한 데이터는 서로 가까이 모여 있다'는 개념을 이용하는 알고리즘.
작동 방식
1. 거리 측정
- 새로운 데이터가 들어오면, 기존에 있던 모든 데이터와의 거리를 계산.
- 보통 유클리드 거리(Euclidean Distance) 를 많이 쓰는데, 쉽게 말하면 '두 점 사이의 직선 거리'이다.

- 맨해튼 거리(Manhattan Distance) 같은 다른 방식도 사용가능.
(맨해튼 거리는 '직선이 아닌 격자형 길을 따라 이동하는 거리'라고 생각하면 됨.)
2. 이웃 선택
- 모든 데이터와의 거리를 구한 뒤, 가장 가까운 k개의 데이터를 선택.
- 여기서 k는 미리 정한 숫자. (예: k=3이면, 가장 가까운 3개의 데이터를 참고함.)
3. 분류 or 회귀 수행
- 분류 (Classification):
- k개의 이웃 중에서 가장 많은 클래스(분류)를 선택해서 새로운 데이터의 클래스를 정한다.
- 예를 들어, 주변에 고양이 2마리, 강아지 1마리가 있다면, 새로운 데이터는 고양이로 분류됨.
- → "다수결 투표(Majority Voting)" 방식
- 회귀 (Regression):
- k개의 이웃들의 값을 평균 내서 예측 값으로 사용.
- 예를 들어, 주변에 온도가 23°C, 25°C, 22°C인 3개의 데이터가 있다면, 새로운 데이터의 온도를 (23+25+22)/3=23.3°C 로 예측하는 식이다.
새로운 데이터가 들어오면 → 기존 데이터와 거리 비교 → 가까운 k개 이웃 찾기 → 다수결(분류) or 평균(회귀)으로 예측!

k-NN 그래프 설명:
- 빨간색 원: 클래스 A에 속하는 데이터 포인트들.
- 파란색 삼각형: 클래스 B에 속하는 데이터 포인트들.
- 초록색 별: 분류되지 않은 새로운 데이터 포인트.
- 점선: 새로운 데이터 포인트와 가장 가까운 k개의 이웃을 연결하는 선. 이 예제에서는 k=3으로 설정되어 있음.
작동방식:
- 새로운 데이터 포인트(초록색 별)와 모든 기존 데이터 포인트(빨간색 원과 파란색 삼각형) 사이의 거리를 계산.
- 가장 가까운 k=3개의 이웃을 선택.
- 선택된 이웃 중 다수결에 따라 새로운 데이터 포인트의 클래스를 결정.
k-NN 알고리즘 장단점
- 장점:
- 이해하고 구현하기 쉽다.
- 새로운 데이터에 대해 학습이 필요 없이 바로 예측 가능.
- 단점:
- 데이터 포인트가 많아지면 계산량이 급격히 증가.
- 데이터의 차원이 높아지면(즉, 특징이 많아지면) 성능이 저하될 수 있음. 이를 차원의 저주(Curse of Dimensionality)라고 한다.
k-NN의 활용 예
- 이미지 분류: 특정 이미지가 어떤 카테고리에 속하는지 분류.
- 추천 시스템: 사용자 간의 유사성을 측정하여 비슷한 선호도를 가진 사용자들에게 유사한 콘텐츠를 추천.
- 의료 진단: 특정 증상을 가진 환자가 어떤 질병에 걸렸는지 예측.
* 한국 청소년들의 의류 구매패턴을 k-NN 알고리즘으로 분석하고 추천
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
# 1. 가상 한국 청소년 의류 구매 패턴 데이터 생성 및 추천 정보 포함
def generate_korean_teen_fashion_data_with_recommendations():
# 데이터 생성
data = {
'Teenager': ['Teen1', 'Teen2', 'Teen3', 'Teen4', 'Teen5', 'Teen6', 'Teen7', 'Teen8', 'Teen9', 'Teen10'],
'Sportswear': [5, 3, 2, 4, 5, 2, 3, 4, 5, 1],
'Casual': [3, 4, 5, 3, 2, 4, 3, 4, 2, 5],
'Luxury': [2, 5, 4, 2, 3, 5, 2, 1, 3, 4],
'Streetwear': [4, 2, 5, 4, 3, 1, 4, 5, 2, 3],
'Fashionable': [5, 4, 3, 5, 4, 3, 2, 5, 4, 3],
'Average_Spending': [100000, 150000, 80000, 95000, 120000, 60000, 110000, 140000, 130000, 90000] # 원 단위
}
df = pd.DataFrame(data)
# 추천 정보 추가
recommendations = {
'Teen1': {'Brand': 'Nike', 'Category': 'Sportswear', 'Spending': 100000},
'Teen2': {'Brand': 'Adidas', 'Category': 'Casual', 'Spending': 150000},
'Teen3': {'Brand': 'Gucci', 'Category': 'Luxury', 'Spending': 80000},
'Teen4': {'Brand': 'Supreme', 'Category': 'Streetwear', 'Spending': 95000},
'Teen5': {'Brand': 'Zara', 'Category': 'Fashionable', 'Spending': 120000},
'Teen6': {'Brand': 'Uniqlo', 'Category': 'Casual', 'Spending': 60000},
'Teen7': {'Brand': 'Puma', 'Category': 'Sportswear', 'Spending': 110000},
'Teen8': {'Brand': 'H&M', 'Category': 'Fashionable', 'Spending': 140000},
'Teen9': {'Brand': 'Adidas', 'Category': 'Casual', 'Spending': 130000},
'Teen10': {'Brand': 'Nike', 'Category': 'Sportswear', 'Spending': 90000}
}
return df, recommendations
# 2. 데이터 로드 및 분할
df, brand_recommendations = generate_korean_teen_fashion_data_with_recommendations()
X = df[['Sportswear', 'Casual', 'Luxury', 'Streetwear', 'Fashionable', 'Average_Spending']]
y = df['Teenager']
# 3. K-NN 모델 학습
knn = KNeighborsClassifier(n_neighbors=3)
knn.fit(X, y)
# 4. 새로운 청소년 구매 패턴 데이터
new_teen = pd.DataFrame({
'Sportswear': [1],
'Casual': [5],
'Luxury': [2],
'Streetwear': [5],
'Fashionable': [3],
'Average_Spending': [50000] # 원 단위로 예상되는 지출 금액
})
# 5. 새로운 청소년의 구매 패턴에 따른 추천 패턴 예측
predicted_teen = knn.predict(new_teen)[0]
print(f"Predicted Teenager Similarity: {predicted_teen}")
# 6. 예측된 청소년 패턴에 따른 추천 브랜드, 카테고리 및 사용 금액
recommendation = brand_recommendations.get(predicted_teen, None)
# 올바른 형태의 데이터로 접근할 수 있도록 수정
if isinstance(recommendation, dict):
print(f"Recommended Brand: {recommendation['Brand']}")
print(f"Recommended Category: {recommendation['Category']}")
print(f"Expected Spending: {recommendation['Spending']} 원")
else:
print("No recommendation available.")
* K-NN 알고리즘을 이용한 MBTI 분석 코드
※ 데이터를 추후에 좀 더 추가해야함. 데이터가 많아질수록 예측 정확도가 높아짐.
mbti계산 외부 모듈 생성하여 업로드 (mbti_explainer.py)
# mbti_explainer.py
# 각 MBTI 유형에 대한 설명을 제공하는 함수ㅣ
def explain_mbti(mbti_type):
descriptions = {
'INTJ': 'INTJ는 분석적이고 독립적인 성향을 지닌 전략가입니다. 비전을 제시하고 체계적으로 문제를 해결합니다.',
'ENFP': 'ENFP는 열정적이고 창의적인 성향을 지닌 사람들로, 새로운 아이디어와 인간관계를 중시합니다.',
'ISTJ': 'ISTJ는 책임감 있고 신뢰할 수 있는 성향을 지닌 사람들로, 규칙과 절차를 중시합니다.',
'ESFP': 'ESFP는 사교적이고 활발한 성향을 지닌 사람들로, 현재의 순간을 즐기며 실용적인 방법을 선호합니다.',
'ENTP': 'ENTP는 독창적이고 변화를 선호하는 성향을 지닌 사람들로, 논쟁을 즐기며 새로운 아이디어에 개방적입니다.',
'INFJ': 'INFJ는 직관적이고 이상주의적인 성향을 지닌 사람들로, 깊은 이해와 공감을 통해 세상을 변화시키려 합니다.',
'ESTJ': 'ESTJ는 조직적이고 지도력이 강한 성향을 지닌 사람들로, 규율을 지키고 효율적으로 목표를 달성합니다.',
'INFP': 'INFP는 이상주의적이고 창의적인 성향을 지닌 사람들로, 깊은 가치와 감정을 중시합니다.',
'ISFJ': 'ISFJ는 따뜻하고 헌신적인 성향을 지닌 사람들로, 사람들을 돌보며 조화를 이루려 합니다.',
'ENTJ': 'ENTJ는 결단력 있고 목표 지향적인 성향을 지닌 지도자들로, 전략적으로 계획하고 리더십을 발휘합니다.',
'ENFJ': 'ENFJ는 외향적이고 사람 중심적인 성향을 지닌 사람들로, 타인을 돕고 영감을 주는 리더입니다.',
'ISTP': 'ISTP는 분석적이고 실용적인 성향을 지닌 사람들로, 문제 해결에 능숙하며 즉흥적인 행동을 선호합니다.'
}
return descriptions.get(mbti_type, "Unknown MBTI type")
# 테스트를 위한 메인 함수
if __name__ == "__main__":
test_type = 'INTJ'
print(f'{test_type}: {explain_mbti(test_type)}')
MBTI 분석하고 예측하는 코드
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score, classification_report
from mbti_explainer import explain_mbti # 외부 모듈 불러오기
# 1. 가상의 MBTI 데이터 생성
# 사용자들의 외향성(Extraversion), 직관(Intuition), 사고(Thinking), 판단(Judging) 점수를 기반으로 MBTI 유형 데이터를 생성합니다.
data = {
'Extraversion': [1, 3, 5, 2, 4, 2, 5, 4, 1, 3, 5, 4], # 외향성 점수: 낮은 점수는 내향성을, 높은 점수는 외향성을 의미
'Intuition': [3, 5, 1, 4, 2, 2, 1, 3, 5, 4, 1, 2], # 직관 점수: 낮은 점수는 감각형(S), 높은 점수는 직관형(N)을 의미
'Thinking': [5, 1, 4, 2, 3, 5, 1, 2, 4, 5, 1, 3], # 사고 점수: 낮은 점수는 감정형(F), 높은 점수는 사고형(T)을 의미
'Judging': [2, 4, 3, 5, 1, 2, 4, 3, 5, 1, 4, 2], # 판단 점수: 낮은 점수는 인식형(P), 높은 점수는 판단형(J)을 의미
'MBTI': ['INTJ', 'ENFP', 'ISTJ', 'ESFP', 'ENTP', 'INFJ', 'ESTJ', 'INFP', 'ISFJ', 'ENTJ', 'ENFJ', 'ISTP'] # MBTI 유형
}
# 데이터를 pandas 데이터프레임으로 변환합니다.
df = pd.DataFrame(data)
# 2. 특징과 레이블로 나누기
# X는 사용자의 특성(외향성, 직관, 사고, 판단)을 포함하며, y는 해당 사용자의 MBTI 유형을 나타냅니다.
X = df[['Extraversion', 'Intuition', 'Thinking', 'Judging']]
y = df['MBTI']
# 3. 데이터 분할 (학습 세트와 테스트 세트)
# 데이터를 학습 세트(70%)와 테스트 세트(30%)로 분할합니다.
# random_state=42로 설정하여 데이터 분할이 항상 동일하게 이루어지도록 합니다.
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# 4. k-NN 모델 학습
# K-NN 알고리즘을 사용하여 모델을 학습합니다. k=3으로 설정하여 가장 가까운 3개의 이웃을 참조합니다.
knn = KNeighborsClassifier(n_neighbors=3)
knn.fit(X_train, y_train)
# 5. 예측 수행
# 학습된 모델을 사용하여 테스트 세트에 대한 예측을 수행합니다.
y_pred = knn.predict(X_test)
# 6. 모델 성능 평가
# 예측 결과의 정확도와 분류 보고서를 출력합니다.
# 정확도는 모델이 정확히 예측한 비율을 의미하며, 분류 보고서는 정밀도, 재현율 등을 포함합니다.
accuracy = accuracy_score(y_test, y_pred)
print(f'Accuracy: {accuracy * 100:.2f}%')
print("\nClassification Report:")
# zero_division=1 옵션을 추가하여 0으로 나누는 경우에 대해 1로 처리합니다.
print(classification_report(y_test, y_pred, zero_division=1))
# 7. 새로운 사용자 데이터 예측
# 새로운 사용자의 특징을 입력하여 MBTI를 예측합니다.
new_user = pd.DataFrame({
'Extraversion': [3], # 외향성: 2점, 이 점수가 낮을수록 내향성에 가깝고, 높을수록 외향성에 가까움
'Intuition': [2], # 직관: 4점, 이 점수가 낮을수록 감각형(S)에 가깝고, 높을수록 직관형(N)에 가까움
'Thinking': [2], # 사고: 3점, 이 점수가 낮을수록 감정형(F)에 가깝고, 높을수록 사고형(T)에 가까움
'Judging': [2] # 판단: 5점, 이 점수가 낮을수록 인식형(P)에 가깝고, 높을수록 판단형(J)에 가까움
})
# 학습된 모델을 사용하여 새로운 사용자에 대한 MBTI 유형을 예측합니다.
predicted_mbti = knn.predict(new_user)[0]
print(f"Predicted MBTI for the new user: {predicted_mbti}")
# 8. 예측된 MBTI 유형에 대한 설명 출력
# 예측된 MBTI 유형에 대한 설명을 외부 모듈에서 불러온 explain_mbti 함수를 통해 출력합니다.
explanation = explain_mbti(predicted_mbti)
print(f"Explanation: {explanation}")
# 위 MBTI 코드를 Flask를 통해 웹서비스로 구현해보는 실습
터미널을 이용해 폴더를 만들고 파일질라를 이용해 파일을 옮긴다.
index.html과 result.html파일은 templates 폴더에, app.py는 templates의 상위폴더에 놓는다.
터미널에서 python3 app.py 입력하여 실행후 'http://vm인스턴스 외부ip주소:포트번호' 로 접속 후 확인.


* 신규고객에 대한 의류 고객 추천시스템 코드
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
# 데이터셋 로드
file_path = '/content/sales.csv'
df = pd.read_csv(file_path)
# 'PurchaseAmount (원)' 컬럼명을 'PurchaseAmount'로 변경
df.rename(columns={'PurchaseAmount (원)': 'PurchaseAmount'}, inplace=True)
# 필요한 데이터 전처리
# 'Age', 'Gender', 'ClothingCategory', 'Brand', 'PurchaseLocation' 등의 열을 사용
X = df[['Age', 'Gender', 'ClothingCategory', 'Brand', 'PurchaseAmount']] # 필요한 특성만 선택
y = df['Email'] # 타겟 변수 (Email)
# 범주형 데이터를 수치형으로 변환
X = pd.get_dummies(X)
# 데이터셋을 학습과 테스트 세트로 분할
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# K-NN 모델 학습
knn = KNeighborsClassifier(n_neighbors=3)
knn.fit(X_train, y_train)
# 새로운 고객 데이터로 예측
new_customer = pd.DataFrame({
'Age': [30],
'Gender': ['Female'],
'ClothingCategory': ['Casual'],
'Brand': ['Nike'],
'PurchaseAmount': [150000] # 구매 금액
})
# 새로운 고객 데이터에 대해 One-Hot Encoding 적용
new_customer = pd.get_dummies(new_customer)
new_customer = new_customer.reindex(columns=X.columns, fill_value=0)
# 가장 유사한 고객의 Email 예측
predicted_customer = knn.predict(new_customer)[0]
# 예측된 고객과 유사한 다른 고객들의 구매 패턴을 확인하고 추천 내용 생성
similar_customers = df[df['Email'] == predicted_customer]
# 입력된 new_customer의 금액에 최대한 유사한 상품 추천
if not similar_customers.empty:
input_amount = new_customer['PurchaseAmount'].values[0]
# 입력 금액과 가장 유사한 상품을 찾기 위해 오차를 계산
df['AmountDifference'] = abs(df['PurchaseAmount'] - input_amount)
# 오차가 작은 상품을 추천 (여기서는 상위 5개의 유사한 상품을 추천)
recommended_products = df.nsmallest(5, 'AmountDifference')
if not recommended_products.empty:
print("추천 상품 목록:")
print(recommended_products[['Brand', 'ClothingCategory', 'PurchaseAmount', 'PurchaseLocation']])
else:
print("추천할 상품이 없습니다.")
else:
print("유사한 고객을 찾을 수 없어 추천할 내용이 없습니다.")
# 위 코드를 Flask를 통해 웹서비스로 구현해보는 실습


* 직접 데이터셋을 만들어 코드 구성 후 Flask를 통해 웹서비스로 구현해보는 실습
# 고객 특성별 카드 추천 시스템을 만들어보자.
1. 카드추천에 도움이 될 만한 고객 특성들을 생각하여 독립변수로 잡고 데이터셋 생성

2. 고객 특성을 고려한 카드 추천시스템 코드 생성 (k-NN 알고리즘 활용)
# 내가 만든 Card 추천시스템
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
# 데이터셋 로드
data = {
'Age': [21, 21, 31, 35, 55, 35, 33, 31, 35, 30],
'Gender': ['Male', 'Male', 'Male', 'Male', 'Male', 'Male', 'Male', 'Male', 'Female', 'Female'],
'Interest': ['Food', 'Technology', 'Technology', 'Food', 'Food', 'Food', 'Sports', 'Food', 'Technology', 'Technology'],
'MonthlyPurchaseAmount': [700000, 850000, 1200000, 4000000, 1800000, 900000, 1500000, 1900000, 2500000, 1000000],
'Occupation': ['Engineer', 'Student', 'Teacher', 'Doctor', 'Student', 'Student', 'Engineer', 'Student', 'Artist', 'Teacher'],
'CreditCardProducts': ['Cashback Credit Card', 'Standard Credit Card', 'Travel Credit Card', 'Premium Credit Card', 'Standard Credit Card',
'Standard Credit Card', 'Premium Credit Card', 'Travel Credit Card', 'Premium Credit Card', 'Cashback Credit Card']
}
df = pd.DataFrame(data)
# 'MonthlyPurchaseAmount' 컬럼명을 'PurchaseAmount'로 변경
df.rename(columns={'MonthlyPurchaseAmount': 'PurchaseAmount'}, inplace=True)
# 필요한 데이터 전처리
# 'Age', 'Gender', 'Interest', 'Occupation', 'PurchaseAmount' 컬럼을 사용
X = df[['Age', 'Gender', 'Interest', 'Occupation', 'PurchaseAmount']] # 필요한 특성만 선택
y = df['CreditCardProducts'] # 타겟 변수 (신용카드상품)
# 범주형 데이터를 수치형으로 변환
X = pd.get_dummies(X)
# 데이터셋을 학습과 테스트 세트로 분할
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# K-NN 모델 학습
knn = KNeighborsClassifier(n_neighbors=3)
knn.fit(X_train, y_train)
# 새로운 고객 데이터로 예측
new_customer = pd.DataFrame({
'Age': [30],
'Gender': ['Female'],
'Interest': ['Technology'],
'Occupation': ['Teacher'],
'PurchaseAmount': [1500000] # 구매 금액
})
# 새로운 고객 데이터에 대해 One-Hot Encoding 적용
new_customer = pd.get_dummies(new_customer)
new_customer = new_customer.reindex(columns=X.columns, fill_value=0)
# 가장 유사한 고객의 신용카드 상품 예측
predicted_card = knn.predict(new_customer)[0]
# 예측된 신용카드 상품과 유사한 다른 고객들의 데이터를 확인하고 추천 내용 생성
similar_customers = df[df['CreditCardProducts'] == predicted_card]
# 입력된 new_customer의 금액에 최대한 유사한 상품 추천
if not similar_customers.empty:
input_amount = new_customer['PurchaseAmount'].values[0]
# 입력 금액과 가장 유사한 상품을 찾기 위해 오차를 계산
df['AmountDifference'] = abs(df['PurchaseAmount'] - input_amount)
# 오차가 작은 상품을 추천 (여기서는 상위 5개의 유사한 상품을 추천)
recommended_products = df.nsmallest(5, 'AmountDifference')
if not recommended_products.empty:
print("추천 상품 목록:")
print(recommended_products[['CreditCardProducts','Interest', 'Occupation', 'PurchaseAmount']])
else:
print("추천할 상품이 없습니다.")
else:
print("유사한 고객을 찾을 수 없어 추천할 내용이 없습니다.")
3. Flask를 통해 웹서비스로 구현하기
터미널을 이용해 폴더를 만들고 파일질라를 이용해 파일을 옮긴다.
index.html과 result.html파일은 templates 폴더에, app.py는 templates의 상위폴더에 놓는다.
터미널에서 python3 app.py 입력하여 실행후 'http://vm인스턴스 외부ip주소:포트번호' 로 접속 후 확인.




이번에는 데이터셋을 간단하게 만들었지만 추후에 데이터를 더 많이 생성하고 카드추천에 유용한 고객의 특성을 더 세부적으로 파악하여 독립변수에 추가한다면 좀 더 정확한 예측을 할 수 있는 추천시스템을 구축할 수 있을 것 같다.
서포트 벡터 머신(SVM)
- 지도학습의 대표적인 분류 알고리즘 - 특히 이진 분류 문제에서 높은 성능을 보임.
- 데이터를 가장 잘 구분하는 "최적의 경계선(초평면)"을 찾는 알고리즘
- 분류(Classification)와 회귀(Regression)에 사용됨
- 가장 가까운 데이터(서포트 벡터)와 초평면 사이의 거리(마진)를 최대화하는 것이 목표
- 데이터가 선형적으로 구분되지 않을 때는 "커널 트릭"을 사용해서 차원을 확장

SVM이 하는 일 (분류 문제 기준)
# 최적의 초평면(Hyperplane) 찾기
- 초평면(Hyperplane)은 데이터를 나누는 선(2D에서는 선, 3D에서는 평면, 고차원에서는 초평면)
- 목표: 두 클래스 간의 마진(Margin) 을 최대화하는 초평면을 찾는 것
- 마진(Margin): 서포트 벡터(Support Vector)와 초평면 사이의 거리
마진을 가장 크게 만드는 초평면이 최적의 결정 경계이다.
SVM의 공식
SVM은 초평면을 수식으로 이렇게 나타낸다:

- = 초평면의 기울기를 나타내는 벡터
- x = 데이터 포인트 (입력 값)
- b = 절편
SVM 커널(Kernel)
- 데이터가 선형적으로 구분되지 않는다면 커널 트릭(Kernel Trick)" 을 사용해서 데이터를 고차원 공간으로 변환할 수 있음.
1. 선형 커널 (Linear Kernel)
- 선형적으로 구분되는 데이터에 사용 - 주로 우리가 볼 것.
2. 다항 커널 (Polynomial Kernel)
- 특징 간의 복잡한 상호작용이 중요한 경우 사용.
3. RBF 커널 (Radial Basis Function Kernel, 가우시안 커널)
- 가장 많이 사용됨.
- 비선형 데이터에 효과적.
4. 시그모이드 커널 (Sigmoid Kernel)
- 신경망과 유사한 방식. 특수한 작업에 사용.
SVM의 활용 사례
- 이미지 분류 (손글씨 숫자 인식, 얼굴 인식 등)
- 텍스트 분류 (스팸 필터링, 감성 분석)
- 의료 데이터 분석 (질병 진단)
그래프로 이해하기

SVM은 주어진 데이터에서 두 클래스를 구분하는 최적의 초평면을 찾는다.
각 클래스의 가장 가까운 데이터 포인트(즉, 서포트 벡터)와 초평면 사이의 거리를 최대화하는 것이 목표.
- 초평면(Hyperplane): 데이터를 분류하는 데 사용되는 경계.
- 마진(Margin): 각 클래스의 서포트 벡터와 초평면 사이의 거리. SVM은 이 마진을 최대화하는 초평면을 찾는다.
- 서포트 벡터(Support Vectors): 각 클래스에서 초평면에 가장 가까운 데이터 포인트들. 이 서포트 벡터는 최적의 초평면을 정의하는 데 중요한 역할을 한다.
- ※ 커널(Kernel): 데이터를 고차원으로 변환하는 함수 (비선형 데이터 처리 가능)

- Decision Boundary: 검정색 선은 SVM이 학습한 초평면(결정 경계)을 나타낸. 이 선은 두 클래스 사이를 최대한 분리하는 역할을 한다.
- Support Vectors: 노란색 점들은 서포트 벡터를 나타낸다. 이 점들은 결정 경계의 위치를 결정하는 데 중요한 역할을 한다.
- Classes: 두 개의 클래스(파란색과 빨간색)로 나뉜 데이터 포인트들. SVM은 이 클래스들을 최대한 분리하는 초평면을 찾음.
# SVM을 이용해 개와 고양이 사진을 학습해 분류하는 예시
※ 개와 고양이 사진 압축 파일
import cv2
import numpy as np
from sklearn import svm
from sklearn.metrics import accuracy_score
from sklearn.model_selection import train_test_split
from skimage.feature import hog
import matplotlib.pyplot as plt
import os
# 1. HOG 특징 추출 함수
def extract_hog_features(image):
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 이미지를 흑백으로 변환
hog_features, hog_image = hog(gray_image, pixels_per_cell=(8, 8),
cells_per_block=(2, 2), visualize=True)
return hog_features
# 2. 이미지 로드 및 전처리
def load_images_from_folder(folder):
images = []
labels = []
for filename in os.listdir(folder):
label = 0 if 'cat' in filename else 1 # 파일명에 'cat'이 포함된 이미지를 고양이로, 그렇지 않으면 개로 라벨링
img = cv2.imread(os.path.join(folder, filename))
if img is not None:
img = cv2.resize(img, (64, 64)) # 이미지 크기를 통일
images.append(extract_hog_features(img))
labels.append(label)
return np.array(images), np.array(labels)
# 3. 데이터 로드
folder_path = '/content/data' # 구글 드라이브에 있는 데이터셋 폴더 경로
X, y = load_images_from_folder(folder_path)
# 4. 데이터셋 분할
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 5. SVM 모델 학습
model = svm.SVC(kernel='linear')
model.fit(X_train, y_train)
# 6. 예측 및 정확도 평가
y_pred = model.predict(X_test)
print(f'Accuracy: {accuracy_score(y_test, y_pred) * 100:.2f}%')
# 7. 테스트 이미지 예측 및 시각화
def predict_image(img_path):
img = cv2.imread(img_path)
img_resized = cv2.resize(img, (64, 64))
features = extract_hog_features(img_resized)
features = features.reshape(1, -1)
prediction = model.predict(features)
if prediction == 0:
print("It's a cat!")
else:
print("It's a dog!")
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.title("Prediction: Cat" if prediction == 0 else "Prediction: Dog")
plt.show()
# 예측 예시
predict_image('/content/data/dog.jpeg')
import matplotlib.pyplot as plt
from sklearn.metrics import roc_curve, roc_auc_score
# 1. 예측 확률 계산 (SVM에서 결정 함수 사용)
y_scores = model.decision_function(X_test)
# 2. ROC 곡선 데이터 계산
fpr, tpr, thresholds = roc_curve(y_test, y_scores)
# 3. AUC 값 계산
auc_score = roc_auc_score(y_test, y_scores)
# 4. ROC 곡선 그리기
plt.figure(figsize=(8, 6))
plt.plot(fpr, tpr, color='blue', label=f'ROC Curve (AUC = {auc_score:.2f})')
plt.plot([0, 1], [0, 1], color='gray', linestyle='--') # 대각선 선: 무작위 예측
plt.xlabel('False Positive Rate (1 - Specificity)')
plt.ylabel('True Positive Rate (Sensitivity)')
plt.title('ROC Curve for SVM Model')
plt.legend(loc='lower right')
plt.grid(True)
plt.show()


※ 여기서 ROC 곡선이란??

ROC 곡선은 분류 모델의 성능을 평가하는 그래프.
특히, 이진 분류(Binary Classification) 모델이 얼마나 잘 작동하는지 시각적으로 보여준다.
ROC 곡선은 True Positive Rate (TPR) vs False Positive Rate (FPR) 를 나타내는 그래프.
왼쪽 위에 가까울수록 성능이 좋은 모델. (그래프가 뒤집어진 기역자)
TPR (True Positive Rate, 민감도 Sensitivity) | FPR (False Positive Rate) |
|
|
복습 - 다중 클래스 로지스틱 회귀
# 로지스틱 회귀를 사용하여 고객 충성도 등급 예측하기
- 0 (낮음): 구매 빈도가 낮고, 재방문 가능성이 낮음
- 1 (중간): 일정 수준의 구매와 재방문 기록이 있음
- 2 (높음): 높은 구매 빈도와 충성도를 보이며, 장기 고객이 될 가능성이 큼
고객의 연령, 월 평균 구매 횟수, 월 평균 구매 금액, 고객 서비스 문의 횟수 등의 정보를 바탕으로 충성도 등급을 예측하는 다중 클래스 분류 모델.
# 고객충성도 등급예측 - 다중 클래스 로지스틱 회귀 코드
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix
# 가상의 고객 데이터 생성
data = {
'age': [22, 45, 25, 33, 50, 41, 29, 39, 48, 23, 31, 36, 27, 40, 53, 44, 26, 38, 51, 30],
'monthly_purchases': [1, 5, 2, 3, 6, 4, 2, 3, 5, 1, 3, 4, 2, 4, 6, 5, 2, 3, 5, 2],
'monthly_spending': [50, 300, 80, 200, 400, 250, 100, 220, 380, 60, 180, 240, 90, 270, 420, 320, 75, 230, 390, 110],
'customer_support_calls': [3, 1, 4, 2, 0, 1, 3, 2, 0, 4, 2, 1, 3, 1, 0, 1, 4, 2, 0, 3],
'loyalty_level': [0, 2, 0, 1, 2, 1, 0, 1, 2, 0, 1, 1, 0, 1, 2, 1, 0, 1, 2, 0] # 0=낮음, 1=중간, 2=높음
}
df = pd.DataFrame(data)
# 독립 변수(X)와 종속 변수(y) 분리
X = df[['age', 'monthly_purchases', 'monthly_spending', 'customer_support_calls']]
y = df['loyalty_level']
# 데이터 분할 (훈련 80%, 테스트 20%)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)
# 데이터 정규화
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)
# 다중 클래스 로지스틱 회귀 모델 학습
model = LogisticRegression(multi_class='multinomial', solver='lbfgs', max_iter=200)
model.fit(X_train, y_train)
# 예측 함수 정의
def predict_loyalty(age, monthly_purchases, monthly_spending, customer_support_calls):
""" 입력값을 받아 고객 충성도 등급을 예측 """
input_data = np.array([[age, monthly_purchases, monthly_spending, customer_support_calls]])
input_scaled = scaler.transform(input_data)
predicted_class = model.predict(input_scaled)[0]
predicted_proba = model.predict_proba(input_scaled)
loyalty_labels = {0: "낮음", 1: "중간", 2: "높음"}
print(f"\n🔹 예측된 고객 충성도 등급: {loyalty_labels[predicted_class]}")
print(f"🔹 각 등급 확률: 낮음={predicted_proba[0][0]:.2f}, 중간={predicted_proba[0][1]:.2f}, 높음={predicted_proba[0][2]:.2f}")
# 예측 예제 실행
predict_loyalty(30, 4, 200, 2) # 나이=30, 월 평균 구매=4회, 월 평균 구매액=200, 고객센터 문의=2회
* 위 코드를 Flask를 통해 웹서비스로 구현하기
터미널을 이용해 폴더를 만들고 파일질라를 이용해 파일을 옮긴다.
index.html파일은 templates 폴더에, app.py는 templates의 상위폴더에 놓는다.
터미널에서 python3 app.py 입력하여 실행후 'http://vm인스턴스 외부ip주소:포트번호' 로 접속 후 확인.


데이터셋이 많을수록 정확한 예측을 보이기 때문에 많은 데이터 확보가 관건이다.
# 로지스틱 회귀를 사용하여 대입 수험생 대학 합격 여부 예측 서비스 만들기
- 대학 합격 여부 (0: 합격, 1: 추합, 2: 불합격)
# 대입 수험생 대학 합격 여부 예측 서비스 만들기 (웹에서도 구현)
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix
# 가상의 데이터 생성
data = {
'Korean': [85, 92, 78, 88, 94, 75, 80, 95, 89, 93, 87, 91, 82, 78, 90, 85, 87, 93, 88, 91, 84, 80, 76, 77, 95, 83, 92, 85, 88, 80],
'Mathematics': [90, 88, 85, 91, 89, 82, 87, 93, 86, 90, 92, 86, 83, 81, 89, 90, 85, 92, 87, 93, 91, 85, 84, 82, 92, 90, 91, 80, 85, 88],
'English': [80, 85, 75, 90, 88, 70, 80, 85, 82, 88, 78, 82, 85, 75, 84, 83, 82, 87, 81, 84, 80, 85, 82, 78, 85, 80, 83, 87, 81, 79],
'Korean_History': [95, 100, 90, 85, 98, 92, 89, 97, 94, 96, 93, 95, 92, 91, 90, 89, 94, 96, 88, 99, 97, 92, 95, 90, 93, 96, 94, 97, 95, 92],
'Inquiry': [88, 92, 85, 91, 94, 80, 85, 89, 87, 90, 88, 90, 85, 92, 91, 86, 85, 87, 92, 89, 88, 91, 92, 90, 90, 87, 93, 85, 88, 89],
'Second_Foreign_Language': [70, 80, 65, 85, 78, 72, 76, 90, 85, 80, 75, 78, 80, 76, 70, 85, 82, 80, 78, 75, 88, 80, 82, 76, 84, 79, 77, 82, 75, 80],
'admission_status': [0, 1, 2, 0, 1, 2, 2, 0, 1, 0, 1, 0, 2, 1, 1, 2, 0, 2, 1, 0, 1, 0, 2, 2, 1, 0, 1, 1, 2, 0] # 대학 합격 여부 (0: 합격, 1: 추합, 2: 불합격)
}
df = pd.DataFrame(data)
# 독립 변수(X)와 종속 변수(y) 분리
X = df[['Korean', 'Mathematics', 'English', 'Korean_History','Inquiry','Second_Foreign_Language']]
y = df['admission_status']
# 데이터 분할 (훈련 80%, 테스트 20%)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)
# 데이터 정규화
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)
# 다중 클래스 로지스틱 회귀 모델 학습
model = LogisticRegression(multi_class='multinomial', solver='lbfgs', max_iter=200)
model.fit(X_train, y_train)
# 예측 함수 정의
def predict_loyalty(Korean, Mathematics, English, Korean_History, Inquiry, Second_Foreign_Language):
input_data = np.array([[Korean, Mathematics, English, Korean_History, Inquiry, Second_Foreign_Language]])
input_scaled = scaler.transform(input_data)
predicted_class = model.predict(input_scaled)[0]
predicted_proba = model.predict_proba(input_scaled)
loyalty_labels = {0: "합격", 1: "추합", 2: "불합격"}
print(f"\n🔹 예측된 대학 합격 확인: {loyalty_labels[predicted_class]}")
print(f"🔹 합격/추합/불합격 확률: 합격={predicted_proba[0][0]:.2f}, 추합={predicted_proba[0][1]:.2f}, 불합격={predicted_proba[0][2]:.2f}")
# 예측 예제 실행
predict_loyalty(100, 80, 70, 90, 70, 90)
* 위 코드를 Flask를 통해 웹서비스로 구현하기


'데이터 분석 part' 카테고리의 다른 글
차원축소, 계층적 군집 분석, 시계열데이터 예측 (회귀분석, 이동평균(MA), 지수 가중 이동 평균 (EMA)) / 마케팅 보고서 작성 연습 (1) | 2025.03.14 |
---|---|
인공신경망(ANN), 다층신경망(MLP), 심층신경망(DNN) / ( 결정트리, 랜덤포레스트, K-평균군집화 복습 ) (0) | 2025.03.13 |
모델 성능 평가와 다중 분류 / 결정 트리의 기본 개념 / 랜덤 포레스트 개념과 구현 (0) | 2025.03.11 |
데이터 전처리, 특징 엔지니어링, 선형회귀, 로지스틱회귀 (0) | 2025.03.11 |
머신러닝의 기본 개념 이해 (2) | 2025.03.10 |