기초 수학과 통계 (2)
가중합 계산
가중합(Weighted Sum)
'가중치'와 '가중합'
NumPy의 np.dot() 함수
가중치 변화가 예측 결과에 미치는 영향을 분석하고, AI 모델의 '학습'이 무엇인지 직관적으로 이해
NumPy 라이브러리
칼로리 소모량 점수
AI 모델이 [운동 시간(분), 평균 심박수(BPM), 체중(lb)] 3가지 요소로 운동 중 소모된 칼로리 점수를 예측
가중합은 각 데이터 값에 해당하는 가중치를 곱한 후, 그 결과들을 모두 더하여 계산
NumPy의 내적(Dot Product) 함수 np.dot()을 사용
계산 공식: (데이터1 × 가중치1) + (데이터2 × 가중치2) + ...
# 예제: 사용자 A의 칼로리 소모량 점수 계산
# 사용자 A의 운동 데이터: [운동 시간: 30분, 평균 BPM: 120, 체중: 150lb]
user_A = np.array([30, 120, 150])
# 가설 1. '운동 시간'이 가장 중요하다고 보는 모델의 가중치
weights_v1 = np.array([5.5, 1.2, 0.8])
# np.dot() 함수로 가중합 계산
calorie_score_A_v1 = np.dot(user_A, weights_v1)
print(f"가설 1 모델로 계산한 사용자 A의 칼로리 점수: {calorie_score_A_v1:.2f}")
가설 1 모델로 계산한 사용자 A의 칼로리 점수: 429.00
가중치를 바꾸어 결과 관찰
새로운 연구 결과, '체중'과 '심박수'가 칼로리 소모에 더 결정적인 요소라는 가설이 제기되었습니다. 이 가설에 따라 가중치를 다음과 같이 조정했습니다.
가설 2 (새로운 가중치): [운동 시간: 3.0, 평균 BPM: 1.8, 체중: 1.5]
사용자 A ([30, 120, 150])의 칼로리 소모량 점수가 이 새로운 가중치에 따라 어떻게 변하는지 np.dot()을 사용하여 계산하고, 결과가 어떻게 달라지는지 관찰해 보세요.
user_B = np.array([240, 145, 7500])
heart_v1 = np.array([0.8, 0.4, -0.002])
score_heartrisk_v1 = np.dot(user_B, heart_v1)
print(f"심장질환 위험도 점수: {score_heartrisk_v1}")
심장질환 위험도 점수: 235.0
여러 환자의 위험도 한번에 계산하기
수많은 환자 데이터를 한번에 처리
NumPy의 np.dot()은 행렬(여러 환자 데이터)과 벡터(가중치) 간의 연산도 지원
반복문 없이 모든 환자의 점수를 한번에 계산
# 예제: 여러 환자의 당뇨병 위험도 점수 계산
# 3명의 환자 데이터를 행렬로 정의: [혈당, 체중, 나이]
patient_matrix = np.array([
[150, 92, 58], # 환자 A
[95, 60, 35], # 환자 C
[180, 110, 62] # 환자 D
])
# 당뇨병 모델 가중치
diabetes_weights = np.array([0.7, 0.2, 0.1])
# 행렬과 벡터의 내적으로 모든 환자의 점수를 한번에 계산!
all_scores = np.dot(patient_matrix, diabetes_weights)
print("모든 환자의 당뇨병 위험도 점수:")
print(f"환자 A: {all_scores[0]:.2f}")
print(f"환자 C: {all_scores[1]:.2f}")
print(f"환자 D: {all_scores[2]:.2f}")
모든 환자의 당뇨병 위험도 점수:
환자 A: 129.20
환자 C: 82.00
환자 D: 154.20
사용자 데이터 행렬(user_matrix)과 위에서 사용한 '가설 2' 칼로리 모델 가중치(weights_v2)를 이용해, 모든 사용자의 칼로리 소모량 점수를 한 줄의 코드로 계산하고 결과를 출력
# 3명의 사용자 데이터: [운동 시간(분), 평균 BPM, 체중(lb)]
user_matrix = np.array([
[30, 120, 150], # 사용자 A
[60, 140, 180], # 사용자 B
[45, 110, 130] # 사용자 C
])
# '가설 2' 칼로리 모델 가중치
weights_v2 = np.array([3.0, 1.8, 1.5])
all_calorie_scores = np.dot(user_matrix, weights_v2)
print(" 칼로리 소모량")
print(f"사용자 A: {all_calorie_scores[0]:.2f}")
print(f"사용자 B: {all_calorie_scores[1]:.2f}")
print(f"사용자 C: {all_calorie_scores[2]:.2f}")
칼로리 소모량
사용자 A: 531.00
사용자 B: 702.00
사용자 C: 528.00
수와 그래프: 예측 모델의 직관적 이해
함수의 기본 개념 이해: AI 모델의 예측 과정을 '입력(Input) → 처리(Process) → 출력(Output)'의 함수 관계
그래프의 시각적 이해: 선형, 지수, 로그, 시그모이드 함수의 그래프 형태를 보고, 각 함수가 어떤 데이터 관계를 표현하는지 직관적으로 파악
헬스케어 예시 적용: Python 코드로 각 함수를 직접 그려보고, 실제 헬스케어 AI 시나리오에서 어떻게 활용되는지 구체적인 예시를 들어 설명
그래프 해석 능력: 그려진 그래프를 보고 데이터의 숨겨진 패턴과 인사이트를 도출
선형 함수 (Linear Function): 꾸준한 비례 관계
공식: y=ax+b
그래프 모양: 끝없이 이어지는 직선.
헬스케어 예시: 수면 시간과 스트레스 지수 감소량
그래프가 직선이라는 것은 변화율이 일정
직선의 기울기(a)는 그 효과의 크기
import numpy as np
# 0부터 10까지 5개의 점으로 나눈 배열 생성
x_points = np.linspace(0, 10, 5)
print(x_points) # 출력: [ 0. 2.5 5. 7.5 10. ]
[ 0. 2.5 5. 7.5 10. ]
atplotlib plt.plot() 주요 옵션: * color: 선의 색상을 지정합니다. ('blue', 'red', 'green', '#FFDD00' 등) * linewidth: 선의 두께를 조절합니다. * linestyle: 선의 스타일을 지정합니다.
('-' (실선), '--' (파선), ':' (점선)) * label: 그래프의 범례(legend)에 표시될 이름을 지정합니다. (이후 plt.legend() 함수 필요)
하루 수면 시간을 1시간부터 10시간까지 가정하고, "수면 1시간당 스트레스 지수 5 감소" 모델을 그래프로 그려봅니다. (기본 스트레스 100에서 시작)
# 입력 데이터: 1시간부터 10시간까지 100개의 점으로 부드럽게 표현
sleep_hours = np.linspace(1, 10, 100)
# 선형 함수 정의: y = -5x + 100
def stress_linear_model(x):
return -5 * x + 100
# 모델로 스트레스 지수 예측
stress_level = stress_linear_model(sleep_hours)
# 그래프 그리기
plt.plot(sleep_hours, stress_level, color='blue', linewidth=3)
plt.title('선형 모델: 수면 시간과 스트레스 지수')
plt.xlabel('수면 시간 (시간)')
plt.ylabel('예측 스트레스 지수')
plt.show()
'고강도 운동'이라는 변수가 추가되어, "수면 1시간당 스트레스 지수가 8씩 감소"하는 새로운 모델을 가정
이 새로운 모델(y = -8x + 100)의 그래프를 기존 그래프에 빨간색 파선(--)으로 추가하여 두 모델을 비교
# TODO: 새로운 선형 함수 정의
def stress_new_linear_model(x):
return -8 * x + 100
# TODO: 새로운 모델로 스트레스 지수 예측
new_stress_level = stress_new_linear_model(sleep_hours)
# 두 그래프 함께 그리기
plt.plot(sleep_hours, stress_level, color='blue', linewidth=3, label='기존 모델 (시간당 -5)')
plt.plot(sleep_hours, new_stress_level, color='red', linewidth=3, linestyle='--', label='고강도 운동 모델 (시간당 -8)')
plt.title('선형 모델 비교: 수면 시간과 스트레스 지수')
plt.xlabel('수면 시간 (시간)')
plt.ylabel('예측 스트레스 지수')
plt.legend() # label 옵션을 화면에 표시
plt.show()
지수 함수 (Exponential Function): 폭발적인 성장 관계
공식: y=ex
그래프 모양: 처음에는 완만하다가 어느 순간부터 기하급수적으로 폭발하듯 치솟는 곡선.
헬스케어 예시: 체내 박테리아 증식 속도
그래프가 뒤로 갈수록 수직에 가깝게 치솟는 것이 핵심입니다. 이는 '성장률' 자체가 계속해서 증가하고 있음을 의미합니다. 헬스케어에서는 "시간이 조금만 더 지나도 상황이 걷잡을 수 없이 악화될 수 있다"는 긴급한 상황을 시각적으로 경고
초기 단계의 개입이 얼마나 중요한지 보여주는 그래프
NumPy np.exp(x): 자연상수 e 의 거듭제곱( ex ) 값을 계산
배열을 입력하면 각 원소에 대해 ex 를 계산하여 반환
시간에 따른 박테리아 수 증식 시각화
0시간부터 5시간까지, 박테리아 수가 시간에 따라 지수적으로 증가하는 모델
# 입력 데이터: 0시간부터 5시간까지
time = np.linspace(0, 5, 100)
# 지수 함수 정의
def bacteria_growth_model(t):
# 2 * e^(t) -> 초기 2마리, 시간당 증식률
return 2 * np.exp(t)
# 시간에 따른 박테리아 수 예측
bacteria_count = bacteria_growth_model(time)
# 그래프 그리기
plt.plot(time, bacteria_count, color='green', linewidth=3)
plt.title('지수 모델: 시간에 따른 박테리아 증식')
plt.xlabel('시간 (시간)')
plt.ylabel('박테리아 수')
plt.show()
영양분이 부족한 환경이라 증식 속도가 더 느린 박테리아를 모델링하려고 합니다. 기존 모델의 식 y = 2 * e^t 에서 지수 부분을 t 대신 0.5 * t 로 변경하여, 새로운 모델 y = 2 * e^(0.5t)의 그래프를 기존 그래프에 주황색 파선으로 추가해 비교해 보세요.
# TODO: 증식 속도가 느린 새로운 지수 함수 정의
def slow_bacteria_growth_model(x):
return 2 * np.exp(0.5*x)
# TODO: 새로운 모델로 박테리아 수 예측
#bacteria_count = bacteria_growth_model(time)
slow_bacteria_count = slow_bacteria_growth_model(time)
# 두 그래프 함께 그리기
plt.plot(time, bacteria_count, color='green', linewidth=3, label='일반 박테리아')
plt.plot(time, slow_bacteria_count, color='orange', linewidth=3, linestyle='--', label='저속 증식 박테리아')
plt.title('지수 모델 비교: 박테리아 증식 속도')
plt.xlabel('시간 (시간)')
plt.ylabel('박테리아 수')
plt.legend()
plt.show()
로그 함수 (Logarithmic Function): 점점 둔화되는 성장 관계
공식: y=log(x)
그래프 모양: 처음에는 빠르게 치솟다가, 점차 성장세가 둔화되며 완만해지는 곡선.
헬스케어 예시: 운동 횟수에 따른 근력 증가량
Insight & 그래프 해석
그래프가 오른쪽으로 갈수록 수평에 가까워지는 것이 핵심입니다. 이는 '수확 체감의 법칙'을 시각적으로 보여줍니다. "초기 투입(노력)은 엄청난 효율을 보이지만, 일정 수준 이상부터는 많은 노력을 해도 얻는 것이 적다"
훈련 프로그램의 효율성을 평가하거나, 약물 효과의 포화점
파이썬 실습
사용 방법 및 주요 함수 안내
NumPy np.log(x): 자연로그( loge(x) ) 값을 계산합니다. 배열을 입력하면 각 원소에 대해 자연로그를 계산하여 반환합니다. (입력값 x는 반드시 0보다 커야 합니다.)
# log(1), log(e), log(10) 값 계산
log_values = np.log([1, np.e, 10])
print(log_values) # 출력: [0. 1. 2.30258509]
[0. 1. 2.30258509]
운동 횟수에 따른 근력 증가 시각화
운동 횟수를 1회부터 100회까지 가정하고, 로그 함수를 이용해 근력 증가 패턴
# 입력 데이터: 1회부터 100회까지의 운동 횟수 (로그 함수는 0을 입력받을 수 없음)
training_sessions = np.linspace(1, 100, 100)
# 로그 함수 정의
def strength_gain_model(sessions):
# 10 * log(sessions) -> 기본 근력 0에서 시작, 훈련에 따라 증가
return 10 * np.log(sessions)
# 운동 횟수에 따른 근력 예측
strength_level = strength_gain_model(training_sessions)
# 그래프 그리기
plt.plot(training_sessions, strength_level, color='purple', linewidth=3)
plt.title('로그 모델: 운동 횟수에 따른 근력 증가')
plt.xlabel('운동 횟수')
plt.ylabel('근력 레벨')
plt.show()
시그모이드 함수 (Sigmoid Function): '예' 또는 '아니오'의 확률
공식: y=1/(1+e−x)
그래프 모양: 알파벳 'S' 형태의 곡선으로, 결코 0 아래로 내려가거나 1 위로 올라가지 않습니다.
헬스케어 예시: 질병 진단 모델의 최종 판단
Insight & 그래프 해석
그래프가 0과 1 사이에 갇혀 있는 것이 핵심
불확실한 예측 점수를 명확한 '확률'로 바꾸어주는 변환 장치
그래프가 급격히 꺾이는 중심(x=0) 부분이 AI의 '결정 경계(Decision Boundary)'
험도 점수가 조금만 변해도 확률이 크게 바뀌므로, 모델이 '긍정'과 '부정' 사이에서 가장 민감하게 반응
파이썬 실습
사용 방법 및 주요 함수 안내
Matplotlib plt.axhline(y, color, linestyle): y 위치에 수평선을 그립니다. 그래프의 특정 기준선을 표시할 때 유용합니다
plt.plot([0, 1], [0, 1]) # 샘플 플롯
# y=0.5 위치에 회색 점선으로 수평선 그리기
plt.axhline(y=0.5, color='grey', linestyle='--')
plt.show()
위험도 점수를 질병 확률로 변환
-10부터 10까지의 가상 '위험도 점수'를 시그모이드 함수에 통과시켜 0과 1 사이의 확률값으로 변환하고 그래프를 그려봅니다.
# 입력 데이터: -10부터 10까지의 위험도 점수
risk_scores = np.linspace(-10, 10, 100)
# 시그모이드 함수 정의
def sigmoid(x):
return 1 / (1 + np.exp(-x))
# 위험도 점수를 확률로 변환
probabilities = sigmoid(risk_scores)
# 그래프 그리기
plt.plot(risk_scores, probabilities, color='orange', linewidth=3)
plt.axhline(y=0.5, color='grey', linestyle='--', label='확률 0.5 (결정 경계)') # 0.5 기준선 추가
plt.title('시그모이드 함수: 위험도 점수를 확률로 변환')
plt.xlabel('AI가 계산한 위험도 점수')
plt.ylabel('질병이 있을 확률 (0.0 ~ 1.0)')
plt.legend()
plt.show()
환자 3명의 위험도 점수가 각각 -7, 0.5, 4.8로 계산되었습니다. 이 점수들을 우리가 정의한 sigmoid 함수를 사용하여 실제 확률값으로 변환하고, 각 확률이 어떤 의미인지 해석해 보세요.
# TODO: 환자들의 위험도 점수
patient_scores = np.array([-7, 0.5, 4.8])
# TODO: 각 점수를 확률로 변환
patient_probabilities = sigmoid(patient_scores)
# TODO: 결과 출력 (예: 위험도 점수 0.0 -> 질병 확률: 0.00%)
print(f"위험도 점수 -7.0 -> 질병 확률: {patient_probabilities[0]*100:.2f}%")
print(f"위험도 점수 0.5 -> 질병 확률: {patient_probabilities[1]*100:.2f}%")
print(f"위험도 점수 4.8 -> 질병 확률: {patient_probabilities[2]*100:.2f}%")
위험도 점수 -7.0 -> 질병 확률: 0.09%
위험도 점수 0.5 -> 질병 확률: 62.25%
위험도 점수 4.8 -> 질병 확률: 99.18%





댓글
댓글 쓰기