Paper: Exposing the Unsaid: Visualizing Hidden LLM Bias through Stochastic Path Aggregation

Listen to this article.

Problem

Large Language Models (LLMs) are known to harbor biases, but these are tricky to spot! Traditional methods of checking LLM outputs—looking at single responses or relying on automated metrics—often miss subtle biases hidden within the model’s probability distributions. This is because LLMs generate text stochastically; they don’t always choose the most likely word, and important bias might lurk in those less common generation paths.

Tech Brief: AI Regulation Tightens as Robotics, Agents Drive Data & Infrastructure Shifts

Tech Brief: AI Regulation Tightens as Robotics, Agents Drive Data & Infrastructure Shifts

Image: How A2A is Building a World of Collaborative Agents — Google Developers Blog

Listen to this article.

Overview

This week’s headlines highlight the ongoing intersection of robotics, cybersecurity regulations, and the evolving landscape of applied AI. The rise of hardware control via software infrastructure (like Kyber), combined with complex regulatory pressures surrounding AI development and deployment, creates a tricky environment for practitioners. Meanwhile, we’re seeing significant investment in physical-world applications—from robotaxis leveraging Japan’s IPO boom to advancements in fusion energy—and a continued refinement of user experience, as demonstrated by e-ink displays and specialized audio players. Finally, the rapid progress in AI agent development showcased through OpenAI’s work is truly worth observing; it’s driving shifts in tooling, data analysis, and potentially even code generation workflows.

빅데이터 분석기사 실기 (Python)

과정 개요

빅데이터 분석기사 실기 시험을 완벽하게 대비하는 Python 기반 실전 과정입니다. 실제 시험 환경과 동일한 조건에서 데이터 분석, 모델링, 평가까지 전 과정을 학습합니다.

과정 정보

학습 목표

  • 빅데이터 분석기사 실기 시험의 3가지 유형 완벽 마스터
  • Python 라이브러리(Pandas, NumPy, Scikit-learn)를 활용한 데이터 분석

커리큘럼

1단계: 작업형 1유형 - 데이터 전처리

  • 데이터 읽기 및 탐색
  • 결측치 처리
  • 이상치 탐지 및 처리
  • 데이터 변환 및 인코딩
  • 그룹화 및 집계

2단계: 작업형 2유형 - 머신러닝 모델링

  • 분류 모델 (로지스틱 회귀, 의사결정나무, 랜덤포레스트 등)
  • 회귀 모델 (선형회귀, Ridge, Lasso 등)
  • 교차 검증 및 하이퍼파라미터 튜닝
  • 모델 평가 지표 (정확도, F1-score, ROC-AUC, RMSE 등)
  • 예측 결과 제출 형식

3단계: 작업형 3유형 - 통계 분석

  • 기술통계 분석
  • 가설 검정
  • 상관분석 및 회귀분석
  • 통계적 유의성 해석

실습 환경

  • 언어: Python

ADsP 회귀분석 상호작용 예시

회귀분석 상호작용 예시

라이브러리 가져오기

  • reshape2 → 데이터 구조 변환(wide↔long), tips 데이터 포함
  • ggplot2 → 시각화(산점도, 회귀선, 상호작용 그래프)
  • lmtest → 회귀 가정 검정(등분산성, 독립성 등)
  • car → 공선성 점검(VIF), 회귀 진단 도구
  • broom → 회귀 결과를 깔끔한 데이터프레임으로 정리
  • emmeans → 상호작용 효과·부분효과(기울기) 통계 검정
library(reshape2)
library(ggplot2)
library(lmtest)
library(car)
library(broom)
library(emmeans)

Tips 데이터 가져오기

  • 데이터 설명 : 미국 식당에서 수집된 팁 관련 표본 데이터
  • 관측치 수: 244
변수명타입설명
total_billnumeric총 결제 금액(달러)
tipnumeric팁 금액(달러)
sexfactor (2)성별 — Female / Male
smokerfactor (2)흡연 여부 — No / Yes
dayfactor (4)요일 — Fri / Sat / Sun / Thur
timefactor (2)식사 시간 — Dinner / Lunch
sizeinteger일행 인원 수
data("tips")                 
str(tips)
## 'data.frame':    244 obs. of  7 variables:
##  $ total_bill: num  17 10.3 21 23.7 24.6 ...
##  $ tip       : num  1.01 1.66 3.5 3.31 3.61 4.71 2 3.12 1.96 3.23 ...
##  $ sex       : Factor w/ 2 levels "Female","Male": 1 2 2 2 1 2 2 2 2 2 ...
##  $ smoker    : Factor w/ 2 levels "No","Yes": 1 1 1 1 1 1 1 1 1 1 ...
##  $ day       : Factor w/ 4 levels "Fri","Sat","Sun",..: 3 3 3 3 3 3 3 3 3 3 ...
##  $ time      : Factor w/ 2 levels "Dinner","Lunch": 1 1 1 1 1 1 1 1 1 1 ...
##  $ size      : int  2 3 3 2 4 4 2 4 2 2 ...

상호작용이 없는 모델 만들기

  • 먼저 상호작용이 없는 모델을 만든다.
m1 <- lm(tip ~ total_bill * sex, data = tips)
summary(m1)
## 
## Call:
## lm(formula = tip ~ total_bill * sex, data = tips)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -3.2232 -0.5660 -0.0977  0.4796  3.6675 
## 
## Coefficients:
##                     Estimate Std. Error t value Pr(>|t|)    
## (Intercept)         1.048020   0.272498   3.846 0.000154 ***
## total_bill          0.098878   0.013808   7.161 9.75e-12 ***
## sexMale            -0.195872   0.338954  -0.578 0.563892    
## total_bill:sexMale  0.008983   0.016417   0.547 0.584778    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 1.026 on 240 degrees of freedom
## Multiple R-squared:  0.4574, Adjusted R-squared:  0.4506 
## F-statistic: 67.43 on 3 and 240 DF,  p-value: < 2.2e-16

계수 해석

  • 계수 해석에 대한 설명은 다음과 같다.
계수 항목추정값(Estimate)표준오차(Std. Error)p-value해석
total_bill0.09890.0138<0.001여성 그룹에서 총금액 1달러 증가 시 팁이 약 $0.099 증가
sexMale-0.19590.33900.564남성은 여성보다 팁이 평균 $0.196 낮지만 통계적으로 유의하지 않음
total_bill:sexMale0.00900.01640.585남성의 기울기가 여성보다 0.009 더 크지만 통계적으로 유의하지 않음
  • 위 표에 대한 해석 가이드는 다음과 같다.
    • (Intercept) : 기준집단(여성)에서 total_bill = 0일 때 팁의 평균값(절편). 실제 상황에서 해석보다는 기준점 역할에 가까움.
    • total_bill : 여성(Female) 그룹 기준으로, 총 결제금액이 1달러 증가할 때 팁이 평균 얼마 증가하는지를 나타냄. 여기서는 0.099달러 증가 → 유의(p<0.001).
    • sexMale : 총 결제금액이 0일 때 남성이 여성보다 팁을 얼마나 더(또는 덜) 주는지의 차이. 여기서는 남성이 여성보다 $0.196 낮지만, 유의하지 않음.
    • total_bill:sexMale : 성별에 따라 총금액이 팁에 미치는 기울기 차이(상호작용). 남성의 기울기가 여성보다 약간(0.009) 높지만 통계적으로 유의하지 않음.

모델 시각화

관측점 + 집단별 loess/선형선(간단)

  • 그래프 코드는 다음과 같다.
ggplot(tips, aes(x = total_bill, y = tip, color = sex)) +
  geom_point(alpha = .6) +
  geom_smooth(method = "lm", se = TRUE) +
  labs(title = "Interaction: total_bill × sex",
       x = "Total bill", y = "Tip", color = "Sex") +
  theme_minimal(base_size = 13)
## `geom_smooth()` using formula = 'y ~ x'

image.png

Open AI와 앤트로픽 API 키 발급받기

Open AI 사이트 확인

  • 사이트 : https://platform.openai.com/
    • 회원가입 및 로그인 필수
  • 톱니바퀴 모양 아이콘(Settings) 클릭 후 설정 화면으로 이동

Screenshot 2025-10-10 at 11.44.36 AM.png

  • 설정화면에서 [API Keys] 메뉴 클릭 후, Create New Secret Key 눌러주기
    • Name : ai-agent-test-project
    • Project : Default Project

Screenshot 2025-10-10 at 11.45.52 AM.png

  • API 키가 보이는 창 확인
    • Copy 버튼 누른 후 클립보드에 저장 후 다른 곳에 잘 저장하기
    • 혹시나 보관을 못했다면, 지우고 다시 생성하는 것 추천
    • 강의 때 연습용으로 사용하는 것은, 추후 관리 소홀로 유출 될 수 있으니 반드시 삭제 권장

Screenshot 2025-10-10 at 11.47.41 AM.png

Logstash 실행 및 확인 - 기본예제

개요

  • Logstash 기본 설치 과정을 확인한다.
  • Logstash 활용 예제를 확인한다.

사전준비

  • 기존에 Elasticsearch와 Kibana 실행 방법을 알고 있어야 한다.
  • 모든 코드는 Windows 에서 실행하였다.

Logstash의 역할

  • 데이터 수집 (Ingest) - 데이터 변환 및 처리 (Processing / Filtering) - 데이터 출력 (Output)

데이터 수집

  • 다양한 데이터 소스로부터 데이터 수집
    • 로그파일
    • TCP/UDP/HTTP 요청
    • Kafka, Redis, JDBC(DB) 등

데이터 변환 및 처리 (Processing / Filtering)

  • 주요 내용

    • Logstash는 수집한 원시 데이터를 구조화된 형식으로 파싱하고 정제 및 가공
    • 정규표현식 기반 grok 필터로 로그 파싱
    • 날짜 포맷 통일 (date)
    • 필드 추가/삭제/이름 변경
    • 조건 분기 처리 (if, else)
    • JSON, CSV 파싱
    • 지오IP, 위치 정보 추가 등
  • 예시 코드

Elasticsearch - Transformers 임베딩 입력 저장 (Local Mode)

개요

  • 엘라스틱서치에서 밀집 벡터 위한 매핑 구성 방법 살펴보기
  • 밀집 벡터가 저장될 embedding 이라는 필드 정의
  • Python 코드로 엘라스틱서치 코드 구현

코드 전체 시나리오

  • Elasticsearch에 연결 및 인덱스 초기화
  • dense_vector 타입으로 매핑 정의
  • 문서 배열 정의
  • BERT 모델을 이용해 각 문서를 벡터 임베딩
  • 벡터 포함 문서를 Elasticsearch에 색인

Elasticsearch 클라이언트 연결

  • 로컬에서 실행 중인 Elasticsearch 서버에 접속
  • basic_auth: 로그인 자격 (ID: elastic, PW: 123456)
  • verify_certs=False: 인증서 검증 생략 (로컬에서 SSL 없이 사용 시 편의용)
es_admin = Elasticsearch("http://localhost:9200", 
                         basic_auth=("elastic", "123456"), 
                         verify_certs=False)

Mapping 정의 및 인덱스 생성

  • dense_vector: 벡터 검색용 필드 (벡터 유사도 기반 검색 가능)
  • dims: BERT의 출력 벡터는 기본적으로 768차원이므로 그에 맞춤
mapping = {
    "properties": {
        "embedding": {
            "type": "dense_vector",
            "dims": 768  # BERT의 출력 벡터 차원 수
        }
    }
}

기존 인덱스 삭제 후 새로 생성

  • 기존에 있던 chapter-2 인덱스를 삭제 (중복 방지)
  • 새로운 인덱스를 위에서 정의한 벡터 매핑으로 생성
try:
    es_admin.indices.delete(index="chapter-2")
    print("기존 chapter-2 인덱스를 삭제했습니다.")
except:
    print("chapter-2 인덱스가 존재하지 않습니다.")

es_admin.indices.create(index="chapter-2", body={'mappings': mapping})
print("새로운 chapter-2 인덱스를 생성했습니다.")

색인할 문서 데이터 구성

  • titletext로 구성된 단순 문서 리스트
  • text는 BERT 임베딩의 입력값이 된다
docs = [
    {"title": "Document 1", "text": "This is the first document"},
    {"title": "Document 2", "text": "This is the second document"},
    {"title": "Document 3", "text": "This is the third document"}
]

BERT 모델과 토크나이저 초기화

  • bert-base-uncased: Hugging Face에서 사전 학습된 BERT 모델
  • AutoTokenizer: 입력 텍스트를 BERT가 이해할 수 있는 토큰으로 변환
  • AutoModel: 텍스트에 대한 BERT 임베딩 추출
tokenizer = AutoTokenizer.from_pretrained("bert-base-uncased")
model = AutoModel.from_pretrained("bert-base-uncased")

BERT 임베딩 생성

  • tokenizer(...): 텍스트를 토큰화하고 PyTorch 텐서로 변환
  • model(**inputs): BERT 실행 → 각 토큰에 대한 임베딩 벡터 반환
  • last_hidden_state.mean(dim=1): 문장의 전체 임베딩을 mean pooling으로 하나의 벡터로 압축 (1×768 벡터)
  • squeeze(0).numpy(): 불필요한 batch 차원 제거 후 NumPy로 변환
  • tolist(): Elasticsearch에 저장 가능하게 리스트 형태로 변환
for doc in docs:
    text = doc["text"]
    inputs = tokenizer(text, return_tensors="pt", padding=True, truncation=True)
    with torch.no_grad():
        outputs = model(**inputs).last_hidden_state.mean(dim=1).squeeze(0).numpy() 
        doc["embedding"] = outputs.tolist()

Elasticsearch에 색인

  • 각 문서를 chapter-2 인덱스에 색인
  • Elasticsearch는 embedding 필드를 dense_vector로 저장하며, 향후 벡터 검색에도 사용 가능
for doc in docs:
    es_admin.index(index="chapter-2", body=doc)

확인

  • Kibana | Management | Dev Tools에서 색인된 문서 조회
GET chapter-2/_search

image.png

엘라스틱 클라우드에 데이터 추가하기 - 예제 (2025, 06)

CH03 - 데이터 추가

개요

  • Cloud에 데이터 추가

이전 예제 확인

파이썬 코드

# 필요한 라이브러리들을 가져옵니다
import time                    # 시간 지연을 위한 라이브러리
import requests               # HTTP 요청을 위한 라이브러리
from bs4 import BeautifulSoup # HTML 파싱을 위한 라이브러리
from elasticsearch import Elasticsearch  # Elasticsearch 클라이언트

# ✅ Elastic Cloud 연결 (API 키 인증 방식)
# Elastic Cloud의 클러스터에 API 키를 사용하여 연결합니다
# API 키는 사용자명/비밀번호 대신 더 안전한 인증 방식입니다
es = Elasticsearch(
    "your_cloud_url",  # Elastic Cloud 클러스터 URL
    api_key="your_api_key"  # API 키
)

# 저장할 인덱스 이름을 상수로 정의합니다
INDEX_NAME = "evan-elk-search"

# ✅ 인덱스 생성 (존재하지 않으면 새로 생성)
# Elasticsearch에서 데이터를 저장할 인덱스가 있는지 확인하고, 없으면 새로 생성합니다
if not es.indices.exists(index=INDEX_NAME):
    es.indices.create(index=INDEX_NAME)  # 새 인덱스 생성
    print(f"✅ Index '{INDEX_NAME}' created.")
else:
    print(f"✅ Index '{INDEX_NAME}' already exists.")

# ✅ 명언 수집 함수 정의
def get_quotes():
    """
    quotes.toscrape.com 웹사이트에서 명언들을 수집하는 함수
    
    Returns:
        list: 수집된 명언 요소들의 리스트 (BeautifulSoup 객체들)
    """
    res = requests.get("http://quotes.toscrape.com")  # 웹사이트에 GET 요청
    soup = BeautifulSoup(res.text, "html.parser")     # HTML을 파싱
    return soup.select(".quote")                       # .quote 클래스를 가진 요소들을 선택하여 반환

# ✅ 30초 간격으로 명언들을 하나씩 저장
# 수집된 명언들을 가져옵니다
quotes = get_quotes()

# 각 명언을 순회하면서 Elastic Cloud에 저장합니다
for i, q in enumerate(quotes):
    # 명언 데이터를 딕셔너리 형태로 구성합니다
    doc = {
        "text": q.select_one(".text").text.strip(),      # 명언 텍스트 추출 (공백 제거)
        "author": q.select_one(".author").text.strip(),  # 저자 이름 추출 (공백 제거)
        "tags": [tag.text for tag in q.select(".tag")]   # 태그들을 리스트로 추출
    }
    
    # Elastic Cloud에 문서를 저장합니다
    res = es.index(index=INDEX_NAME, document=doc)
    print(f"[{i+1}] ✅ Saved to Elastic Cloud: {res['_id']}")  # 저장된 문서의 ID 출력
    
    # 30초 대기 (다음 명언 저장 전)
    time.sleep(30)
  • 클라우드에서 확인

image.png

엘라스틱 서치 시작하기 - 예제 (2025, 06)

개요

  • 엘라스틱 클라우드 활용 예제 확인

회원가입

image.png

  • 가입 중간에 데이터 저장하는 공간이 있는데, 필자는 GCP를 선택하였다.

image.png

  • 다음 화면에서는 다음과 같이 지정하였다. General Purpose

image.png

  • 인덱스 명 : evan-elk-search

image.png

  • 인덱스 명을 확인하면 다음과 같다.
  • URL과 API 주소를 확인한다.
    • URL : your_url
    • your_api_key

image.png

설치 및 예제 확인

Windows 10

image.png

  • 압축 파일을 해제하고 C 드라이브쪽으로 폴더를 이동시킨다.

BigQuery 데이터 입출력 From Local TO BigQuery

개요

  • 서비스 계정 추가 후, 데이터 업로드

GCP 서비스 계정 추가

  • IAM 및 관리자 > 서비스 계정 > 서비스 계정 만들기 선택

image.png

  • 서비스 계정 이름은 각자 정한다. 필자는 lgu6th-bq-loader로 명명했다.
  • 서비스계정 ID는 이메일 주소 ID를 사용한다.
  • 만들고 계속하기 버튼을 클릭한다.

image.png

  • 권한을 부여한다. BigQuery 관리자를 선택한다.
  • 그 후 계속 버튼을 클릭한다.

image.png

  • 그 후 완료 버튼을 클릭한다.

image.png

서비스 키 다운로드

  • 다음과 같은 화면에서 키 관리 버튼을 클릭한다.

image.png