정종현 강사님
인간의 지적 능력을 컴퓨터에서 구현하는 기술로 고도의 문제 해결 능력을 지닌 인공적인 지능. AI는 인간의 학습능력, 추론능력, 지각능력 등을 컴퓨터 과학을 통해 구현하려는 목표를 가지고 있고, 데이터 분석, 추론, 예측, 분류, 자연어 처리, 추천 시스템 등에 널리 사용된다.
주어진 데이터에서 규칙을 학습하여 새로운 데이터에 대해 예측하는 데이터 과학의 한 분야. 기존의 프로그래밍 방식과 달리 머신러닝은 명시적 지시가 아닌 데이터 기반 학습을 통해 패턴을 찾고 작업을 수행한다.
정답 데이터(라벨)가 포함된 데이터 세트를 사용하여 학습하는 방식. 모델은 입력과 출력 간의 관계를 학습하여 주어진 데이터에 대한 예측을 수행할 수 있다.
정답 데이터 없이 주어진 데이터의 패턴이나 구조를 학습하는 방식. 모델은 입력 데이터의 특징을 바탕으로 비슷한 항목을 그룹화하거나 패턴을 파악할 수 있다.
주어진 데이터를 모델에 적용해 미리 정의된 범주(카테고리) 중 하나로 분류하는 알고리즘. 분류 알고리즘은 지도 학습 방식의 한 유형으로 입력 데이터에 대한 정답(라벨)이 주어져 있으며 이를 통해 학습한 모델은 새로운 데이터에 대해 적합한 범주를 예측할 수 있다.
모델을 배포하고 사용할 수 있는 네트워크 접근점(URL). 엔드포인트는 모델 예측을 위한 요청을 받을 수 있는 안정적이고 내구성 있는 URL을 제공한다.
데이터 분석 및 인공지능 모델을 CLI(명령어 인터페이스)뿐 아니라 웹 기반 GUI로 제공하면 사용 편의성이 크게 향상된다. 특히 데이터 입력과 결과 확인 과정을 시각적으로 제공해 사용자와의 상호작용성을 높일 수 있다.
import json
import gradio as gr
import requests
import matplotlib.pyplot as plt
request_iris_prediction
함수def request_iris_prediction(data_list):
endpoint = "~"
headers = {
"Authorization": "Bearer ~"
}
body = {
"Inputs": {
"input1": data_list
}
}
response = requests.post(endpoint, headers=headers, json=body)
if response.status_code == 200:
response_json = response.json()
return response_json["Results"]["WebServiceOutput0"]
else:
return list()
endpoint
: Azure Machine Learning의 엔드포인트 URL. API 요청이 이 URL로 전송된다.headers
: 요청의 인증 정보를 포함한다.Authorisation
헤더에 Bearer 토큰 방식으로 API 키를 전달해 인증을 수행한다.body
: 예측 요청에 필요한 입력 데이터를 JSON 형식으로 준비한다.data_list
: 함수에 전달된 입력 데이터로 'Inputs'
의 'input1'
키에 배치된다.requests.post
: POST 요청을 전송하고 엔드포인트에서 예측 결과를 수신한다.200
: 요청이 성공하면 JSON 형식의 응답을 파싱해 'Results'
필드에서 'WebServiceOutput0'
의 값을 추출해 반환한다.save_plot
함수def save_plot(data_points):
centroid_positions = {0: [0, 0], 1: [0, 0], 2: [0, 0]}
centroid_colors = {0: 'b', 1: 'r', 2: 'g'}
centroid_poisitions
: 클러스터 중심 위치를 저장하기 위한 딕셔너리. 3개의 클러스터(0, 1, 2)의 평균 위치를 저장한다.centroid_colors
: 각 클러스터의 색상을 지정. 0번 클러스터는 파란색('b'
), 1번은 빨간색('r'
), 2번은 초록색('g'
).# 데이터 포인트 기반으로 클러스터 중심 계산
for point in data_points:
assignment = point["Assignments"]
for i in range(3):
dist_key = f"DistancesToClusterCenter no.{i}"
if dist_key in point:
centroid_positions[i][0] += (point["sepal_length"] + point[dist_key]) / 2
centroid_positions[i][1] += (point["sepal_width"] + point[dist_key]) / 2
for point in data_points
: 각 데이터 포인트를 순회하며 해당 포인트의 Assignments
값에 따라 클러스터 번호를 확인한다.dist_key = f'DistancesToClusterCenter no.{i}
: DistancesToClusterCenter no.{i}
키가 있는지 확인하고 있으면 클러스터 중심 좌표를 업데이트한다.centoriod_positions[i][n]
: 중심 위치에 sepal_length
와 sepal_width
값들을 더해 평균을 구하기 위한 준비 작업.# 클러스터 중심 위치의 최종 평균 계산
for i in range(3):
centroid_positions[i][0] /= len(data_points)
centroid_positions[i][1] /= len(data_points)
# 데이터 포인트 및 클러스터 중심 시각화
plt.figure(figsize=(8, 6))
point_index = 0
for point in data_points:
point_index += 1
plt.scatter(point["sepal_length"], point["sepal_width"],
c='b' if point["Assignments"] == 0 else 'r' if point["Assignments"] == 1 else 'g')
plt.text(point["sepal_length"], point["sepal_width"], f"{point_index}")
plt.scatter(~)
: sepal_length
와 sepal_width
를 x축과 y축 값으로 사용해 각 데이터 포인트를 해당 클러스터 색상으로 표시한다.plt.text(~)
: 각 데이터 포인트의 좌표 옆에 인덱스를 표시하여 식별이 가능하게 한다.# 클러스터 중심 시각화
for cluster, (x, y) in centroid_positions.items():
plt.scatter(x, y, c=centroid_colors[cluster], marker='X', s=200)
x
마커로 표시하고 중심 위치를 지정한 색상으로 그린다.# 플롯 설정 및 저장
plt.title('Data Points and Cluster Centroids')
plt.xlabel('Sepal Length (cm)')
plt.ylabel('Sepal Width (cm)')
plt.grid()
plt.savefig('iris_clusters.png')
plt.close()
return 'iris_clusters.png'
with gr.Blocks() as demo:
view_count = gr.State(1)
data_dict = dict()
with gr.Blocks()
: Gradio 블록 레이아웃을 정의해 UI 컴포넌트를 구성한다.view_count
: 현재 입력 필드 개수를 저장하는 Gradio 상태 변수. 필드 추가 및 삭제 시 상태가 업데이트된다.data_dict
: 입력 데이터를 저장하는 딕셔너리로 각 입력 필드에 입력된 데이터를 저장한다. def click_add(count):
count += 1
print(count)
return count
count
값을 증가시켜 새로운 필드의 추가를 트리거한다. def click_delete(count):
if count > 1:
count -= 1
print(count)
return count
count
값을 감소시킨다. def click_send():
data_list = list(data_dict.values())
response_data = request_iris_prediction(data_list=data_list)
save_plot(response_data)
return response_data, "iris_clusters.png"
data_dict
)에서 값을 추출해 모델에 전달한다.data_list = list(data_dict.values())
: data_dict
의 값들을 리스트로 변환하여 예측 함수에 전달할 준비를 한다.request_iris_prediction
함수에 data_list
를 전달해 Azure Machine Learning 모델에서 예측 결과를 받는다.save_plot
함수로 예측 결과를 시각화 해 파일로 저장한다. def change_data(i, sl, sw, pl, pw):
data_dict.update({
i: {
"sepal_length": sl,
"sepal_width": sw,
"petal_length": pl,
"petal_width": pw,
"class": "unknown"
}
})
print(data_dict)
data_dict
에 값을 업데이트한다.i
: 각 입력 필드의 인덱스. gr.Markdown("# 붓꽃 예측")
gr.Markdown
: 페이지 상단에 제목 # 붓꽃 예측
을 마크다운 형식으로 추가하여 UI의 헤더를 만든다.# 필드 추가 및 삭제 버튼
with gr.Row():
add_button = gr.Button("+")
delete_button = gr.Button("-")
gr.Row()
: UI 상에서 +
와 -
버튼을 한 줄에 배치한다.add_button
: +
버튼. 필드를 추가하기 위한 버튼이다.delete_button
: -
버튼. 필드를 삭제하기 위한 버튼이다.click_add
, click_delete
)가 호출되어 필드 수를 조정한다.# 데이터 입력 필드 구성
with gr.Column():
@gr.render(inputs=[view_count])
def render_input_components(count):
for i in range(0, count):
with gr.Column():
gr.Markdown(f"Index: {i}")
row_index = gr.State(i)
with gr.Row():
sepal_length_number = gr.Number(label="꽃받침 길이", key=f"sepal-length-{i}", value="")
sepal_width_number = gr.Number(label="꽃받침 너비", key=f"sepal-width-{i}", value="")
petal_length_number = gr.Number(label="꽃잎 길이", key=f"petal-length-{i}", value="")
petal_width_number = gr.Number(label="꽃잎 너비", key=f"petal-width-{i}", value="")
@gr.render(inputs=[view_count])
: view_count
를 기반으로 입력 필드의 개수를 렌더링한다.for i in range(0, count)
: count
값만큼 반복하여 각 입력 필드 세트를 렌더링한다.gr.Markdown(f'Index: {i}')
: 각 필드 세트 위에 Index: {i}
를 마크다운 형식으로 표시해 사용자에게 필드 번호를 알려준다.gr.State(i)
: 각 필드 세트의 고유 인덱스 i
를 상태로 저장하여 필드 값을 고유하게 식별할 수 있도록 한다.sepal_length_number
, sepal_width_number
, petal_length_number
, petal_width_number
: 각각의 특징(길이와 너비)에 대한 값을 입력 받는 gr.Number
필드.key
: 필드의 고유 식별자로 설정하여 필드를 동적으로 관리할 수 있게 한다.# `change` 이벤트 설정
sepal_length_number.change(fn=change_data, inputs=[row_index,
sepal_length_number, sepal_width_number, petal_length_number, petal_width_number],
outputs=[])
# 나머지 필드도 동일하게 설정.
change
: 각 입력 필드의 값이 변경될 때마다 change_data
함수가 호출된다.row_index
, sepal_length_number
, sepal_width_number
, petal_length_number
, petal_width_number
값을 전달해 data_dict
에 업데이트.outputs=[]
: 출력을 반환하지 않으므로 빈 리스트로 설정된다. result_textbox = gr.Textbox(label="결과")
result_image = gr.Image(label="결과 이미지", type="filepath")
send_button = gr.Button("전송")
result_textbox
: 예측 결과를 텍스트로 표시하기 위한 gr.Textbox
컴포넌트.reulst_image
: 예측 결과를 시각화하기 위한 gr.Image
컴포넌트.send_button
: 사용자가 모든 입력을 마치고 예측을 요청할 때 클릭하는 전송 버튼.# 버튼 클릭 이벤트 연결
add_button.click(fn=click_add, inputs=[view_count], outputs=[view_count])
delete_button.click(fn=click_delete, inputs=[view_count], outputs=[view_count])
send_button.click(fn=click_send, inputs=[], outputs=[result_textbox, result_image])
add_button.click
fn=clilck_add
: click_add
함수가 호출된다. 이 함수는 view_count
를 1 증가시켜 필드를 추가한다.inputs=[view_count]
: 현재 입력 필드의 개수를 나타내는 view_count
를 전달한다.outputs=[view_count]
: 필드 개수 변경 후 업데이트된 view_count
가 UI에 반영된다.send_button.click
outputs=[result_textbox, result_image]
: 예측된결과가 텍스트(result_textbox
)와 이미지(result_image
)로 반환된다.demo.launch(debug=True)
demo.launch()
demo
로 정의된 Gradio 블록 전체를 실행하여 브라우저에서 접근할 수 있는 웹 애플리케이션으로 띄운다.debug=True
: 앱 실행 중 발생하는 오류나 상세 로그를 콘솔에 표시하여 개발자가 쉽게 디버깅할 수 있도록 한다.