GDA(Gaussian Discriminant Analysis)

November·2024년 9월 27일
post-thumbnail

1. 데이터 불러오기

df3 = pd.read_csv('iris.csv', names=["SepalLength", "SepalWidth", "PetalLength", "PetalWidth", "Species"])

pandas 라이브러리의 read_csv() 함수: csv 파일을 읽어서 데이터프레임으로 변환
names 파라미터 -> 데이터 파일에 헤더(열 이름)가 없는 경우, 각 열에 사용자 정의 헤더를 지정할 수 있음

df3라는 데이터프레임으로 불러옴

df3['SepalLength'] = df3['SepalLength'].astype(float)
df3['SepalWidth'] = df3['SepalWidth'].astype(float)
df3['PetalLength'] = df3['PetalLength'].astype(float)
df3['PetalWidth'] = df3['PetalWidth'].astype(float)

astype(float)로 데이터 타입 변환
데이터셋의 숫자 데이터가 실수형으로 처리되도록 보장하기 위해 각 열의 데이터를 float 타입으로 변환

#라벨 인코딩
df3['Species'] = df3['Species'].apply(lambda x: 0 if x == "Iris-virginica" else (1 if x == "Iris-versicolor" else 2))

문자열 대신 숫자형 데이터를 처리할 수 있도록 라벨 인코딩
Species 열의 문자열로 되어있는 꽃 종류를 숫자로 변환하는 과정
apply() : 데이터프레임의 특정 열에 대해 함수 적용
lambda: 간단한 익명 함수를 정의할 때 사용

2. Features와 Labels 나누기

X = df3[['SepalLength', 'SepalWidth', 'PetalLength', 'PetalWidth']]
y = df3['Species']

3. 데이터 분할

75% training set, 25% testing set

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=42)

train_test_split() : 인자로 받은 x,y를 지정한 비율(test_size)로 분배

클래스별로 데이터 분리

# 클래스별로 데이터 분리
class_means = {}
class_stds = {}

GDA(Gaussian Discriminant Analysis)는 각 클래스별로 데이터의 분포가 가우시안 분포(정규분포)를 따른다고 가정. 각 클래스는 특정 평균과 표준편차를 가진 정규 분포로 모델링됨

각 클래스에 속하는 데이터들의 특징(SepalLength, SepalWidth, PetalLength, PetalWidth)이 어떤 분포를 가지는지 추정 -> 새로운 데이터가 주어졌을 때 그 데이터가 어떤 클래스에 속할 확률을 계산하는 것이 목표

class_means : 각 클래스의 평균을 저장
class_stds : 각 클래스의 표준편차 저장

4. 클래스별 평균과 표준편차 계산

for class_label in np.unique(y_train): #클래스별로 반복
    X_class = X_train[y_train == class_label] #특정 클래스에 해당하는 데이터 선택
    class_means[class_label] = X_class.mean().values #해당 클래스의 각 열에 대해 평균 계산
    class_stds[class_label] = X_class.std().values # 표준편차 계산 

    print(f"Class {class_label} mean: {class_means[class_label]}")
    print(f"Class {class_label} std: {class_stds[class_label]}\n")

np.unique(y_train) 은 y_train에 있는 고유한 클래스 값 반환 -> 0,1,2 세가지 클래스 반환
y_train은 훈련 데이터의 레이블(종속변수). 이 배열에는 0,1,2로 인코딩된 클래스 값 포함
0: Iris-virginica
1: Iris-versicolor
2: Iris-setosa

X_train[y_train==class_label]

y_train에서 해당 클래스(0, 1, 2)에 속하는 데이터 포인트 선택

X_class.mean().values
.values는 계산된 평균을 NumPy 배열로 변환하여 저장
class_means[class_label] = X_class.mean().values
현재 클래스에 해당하는 속성들의 평균을 class_means 딕셔너리에 저장

5. 가우시안 확률 계산 함수

def gaussian_probability(x, mean, std):
    exponent = np.exp(- ((x - mean) ** 2) / (2 * std ** 2))
    return (1 / (np.sqrt(2 * np.pi) * std)) * exponent

6. 각 테스트 데이터에 대해 클래스 확률 계산

def predict(X_test_sample, class_means, class_stds):
    class_probs = [] #각 클래스에 대한 확률을 저장할 리스트 
    for class_label in class_means: #각 클래스에 대해 반복
        # 각 feature별로 가우시안 확률 계산 후 로그 합산
        probs = gaussian_probability(X_test_sample, class_means[class_label], class_stds[class_label])
        class_probs.append(np.log(probs).sum()) #확률들의 로그 합산
    return np.argmax(class_probs) #가장 높은 로그 확률을 가진 클래스 반환 

class_means: 클래스별 각 속성의 평균
class_stds: 클래스별 각 속성의 표준편차

7. 테스트 데이터로 예측

y_pred = []
for i in range(X_test.shape[0]):
    y_pred.append(predict(X_test.iloc[i].values, class_means, class_stds))

X_test.shape[0] : 테스트 데이터셋에 있는 샘플 개수 나타냄
테스트 데이터셋의 각 샘플에 대해 한 번씩 반복, 각 샘플에 대해 예측 수행
X_test.iloc[i] : X_test에서 i번째 샘플의 데이터를 가져오는 코드 (데이터 접근할 때 사용하는 함수)
X_test.iloc[i].values는 이 데이터를 배열(Numpy array)로 변환

8. 정확도 계산

accuracy = np.mean(y_pred == y_test)
print(f"Testing Accuracy: {accuracy * 100:.2f}%")

y_pred : 예측한 클래스 레이블 리스트
y_test : 실제 클래스 레이블

np.mean(y_pred == y_test)
True는 1로, False는 0으로 처리, Boolean 배열에 대해 평균 계산

0개의 댓글