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: 간단한 익명 함수를 정의할 때 사용
X = df3[['SepalLength', 'SepalWidth', 'PetalLength', 'PetalWidth']]
y = df3['Species']
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 : 각 클래스의 표준편차 저장
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 딕셔너리에 저장
def gaussian_probability(x, mean, std):
exponent = np.exp(- ((x - mean) ** 2) / (2 * std ** 2))
return (1 / (np.sqrt(2 * np.pi) * std)) * exponent
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: 클래스별 각 속성의 표준편차
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)로 변환
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 배열에 대해 평균 계산