🧠 LLM 엔지니어링

자연어 처리 기반 가격 예측 모델 개발💸 (BOW vs Word2Vec vs RF) 02

개발자 린다씨 2025. 5. 2. 12:27
반응형

🔰 개요

제품 설명 텍스트만을 가지고 가격을 예측하는 머신러닝 모델을 실험해 봅니다.

Baseline 모델부터 시작해서 BOW, Word2Vec, SVR, 랜덤 포레스트까지 점진적으로 성능을 개선해 나가는 과정을 코드와 함께 단계별로 정리합니다.


7. 📈 수치형 특성을 활용한 선형 회귀 실험

📈 선형 회귀(Linear Regression)를 이용한 가격 예측

아래는 전통적인 선형 회귀 모델을 학습하고 평가하는 전체 코드이며,

feature들을 실제 회귀 모델에 넣어 가격 예측 실험을 해보는 단계입니다.

# 📈 전통적인 선형 회귀 모델 실험

np.random.seed(42)
# 🔒 무작위성 제어 (결과 재현 가능하도록 시드 고정)

# 🧩 입력 특성과 타깃 변수 분리
feature_columns = ['weight', 'rank', 'text_length', 'is_top_electronics_brand']
# - 사용할 특성(feature) 컬럼들 정의

X_train = train_df[feature_columns]  # 📘 학습용 입력 데이터 (피처)
y_train = train_df['price']          # 💰 학습용 정답값 (가격)
X_test = test_df[feature_columns]    # 📗 테스트용 입력 데이터
y_test = test_df['price']            # 💰 테스트용 정답값

# 🤖 선형 회귀 모델 학습
model = LinearRegression()
model.fit(X_train, y_train)
# - X_train 데이터를 기반으로 선형 회귀 모델 학습

# 🔍 학습된 계수 출력
for feature, coef in zip(feature_columns, model.coef_):
    print(f"{feature}: {coef}")
# - 각 특성(feature)의 가중치(회귀 계수)를 출력하여 영향력 확인

print(f"Intercept: {model.intercept_}")
# - 절편(intercept) 값 출력

# 📊 테스트 데이터 예측 및 성능 평가
y_pred = model.predict(X_test)
# - 테스트 데이터셋에 대해 가격 예측 수행

mse = mean_squared_error(y_test, y_pred)  # 평균 제곱 오차 (예측 오차의 평균)
r2 = r2_score(y_test, y_pred)             # 결정 계수 R² (0~1 사이, 높을수록 좋음)

print(f"Mean Squared Error: {mse}")
print(f"R-squared Score: {r2}")
# - 예측 성능을 수치로 출력

📌 출력값 예시 해석 팁:

  • weight: 32.15 → 무게가 1 파운드 늘어나면 가격이 $32.15 올라감
  • r2 = 0.52 → 전체 가격 변동성 중 약 52%를 이 모델이 설명함

🤖 선형 회귀 기반 가격 예측 함수 정의

이 함수는 학습된 선형 회귀 모델을 사용해 새로운 아이템의 가격을 예측하는 용도예요.

# 🤖 새로운 아이템에 대해 가격을 예측하는 함수 (선형 회귀 기반)

def linear_regression_pricer(item):
    features = get_features(item)
    # 🧩 아이템에서 필요한 특성(weight, rank, text_length 등)을 추출

    features_df = pd.DataFrame([features])
    # 📊 추출한 특성을 pandas DataFrame으로 변환 (1개의 row, 여러 column)
    # - scikit-learn 모델은 DataFrame 또는 배열 형태의 입력을 요구함

    return model.predict(features_df)[0]
    # 💰 학습된 선형 회귀 모델로 예측 수행
    # - 결과는 리스트로 반환되므로 [0]을 사용해 숫자 하나만 추출

이 함수는 나중에 Tester.test(linear_regression_pricer) 형태로
전체 테스트셋에 대해 성능을 평가하는 데 활용될 수 있어요.

🧪 선형 회귀 모델 성능 테스트 실행

아래는 선형 회귀 기반 예측 모델을 실제로 평가해 보는 단계예요.

# 🧪 선형 회귀 모델 성능 평가 실행

Tester.test(linear_regression_pricer)
# - 앞서 정의한 linear_regression_pricer 함수에 대해 Tester 클래스를 통해 테스트 실행
# - 테스트셋의 250개 아이템에 대해 예측 수행
# - 각 예측값과 실제값을 비교하여 오차, RMSLE, 정확도(Hits) 등을 출력
# - 동시에 예측 vs 실제값을 시각화한 산점도 그래프도 자동 생성됨

🧠 이 테스트는 피처 기반 선형 회귀 모델이

무작위 모델이나 평균값 모델보다 얼마나 더 잘 예측하는지 확인할 수 있는 중요한 평가 도구예요.

📄 텍스트 기반 모델을 위한 문서 및 가격 데이터 준비

아래는 prices와 documents 리스트를 준비하는 코드이며,

다음 단계에서는 텍스트 기반 모델(BOW, Word2Vec 등)을 위한 데이터를 준비하게 됩니다.

# 📄 텍스트 기반 모델을 위한 데이터 준비
# ⚠️ 주의: test_prompt()를 사용해야 가격(정답)을 유추할 수 없도록 방지!

prices = np.array([float(item.price) for item in train])
# 💰 학습 데이터의 실제 가격을 float 형태의 numpy 배열로 변환
# - 모델의 타깃(label)으로 사용될 값

documents = [item.test_prompt() for item in train]
# 📝 각 아이템의 입력 텍스트(prompt)를 리스트로 저장
# - 반드시 item.test_prompt()를 사용해야 함!
# - 만약 일반 prompt를 사용하면 정답(가격)이 힌트로 노출될 수 있음

🧠 이 코드는 이후 텍스트 임베딩 모델 (CountVectorizer, Word2Vec 등)에서
입력으로 사용할 문서와 예측 목표인 가격 데이터를 분리해주는 역할을 합니다.

🧺 8. Bag of Words(BOW) 기반 회귀 모델

아래는 CountVectorizer를 사용해 Bag of Words(BOW) 모델을 구성하고 선형 회귀를 학습하는 코드입니다.

# 🧺 Bag of Words(BOW) 모델을 위한 CountVectorizer 사용

np.random.seed(42)
# 🔒 재현 가능한 결과를 위해 랜덤 시드 고정

vectorizer = CountVectorizer(max_features=1000, stop_words='english')
# 🧠 CountVectorizer: 텍스트를 단어 등장 횟수 벡터로 변환하는 도구
# - max_features=1000: 가장 자주 등장하는 상위 1000개의 단어만 사용
# - stop_words='english': 의미 없는 일반 단어들(예: the, is 등)은 제거

X = vectorizer.fit_transform(documents)
# 🧾 학습용 텍스트 문서(documents)를 BOW 형태의 희소 행렬(sparse matrix)로 변환
# - 각 행은 문서, 각 열은 단어의 등장 횟수

regressor = LinearRegression()
# 🤖 선형 회귀 모델 생성

regressor.fit(X, prices)
# 📊 변환된 텍스트 벡터(X)와 가격(prices)을 사용하여 회귀 모델 학습

🧠 이 코드는 텍스트 설명만을 기반으로 가격을 예측하는
"텍스트 기반 선형 회귀 모델" 을 구성하는 첫 단계입니다.

🧺 Bag of Words + 선형 회귀 기반 예측 함수 정의

아래는 Bag of Words + 선형 회귀 모델을 사용해 새로운 아이템의 가격을 예측하는 함수입니다.

# 🧺 Bag of Words + 선형 회귀 기반 가격 예측 함수

def bow_lr_pricer(item):
    x = vectorizer.transform([item.test_prompt()])
    # 🧾 입력 아이템의 프롬프트를 BOW 벡터로 변환
    # - item.test_prompt(): 정답(가격)이 노출되지 않도록 안전한 입력
    # - vectorizer는 학습 단계에서 만든 CountVectorizer 객체

    return max(regressor.predict(x)[0], 0)
    # 🤖 선형 회귀 모델을 통해 가격 예측 수행
    # - 결과가 0보다 작을 경우, 최소값을 0으로 보정 (음수 가격 방지)

🧠 이 함수는 텍스트 설명만을 입력으로 받아 정량적인 가격 예측값을 반환합니다.

🧪 BOW + 선형 회귀 모델 성능 테스트

Bag of Words + 선형 회귀 모델의 실제 성능을 평가하는 단계예요.

# 🧪 Bag of Words + 선형 회귀 모델 성능 평가 실행

Tester.test(bow_lr_pricer)
# - 앞서 정의한 bow_lr_pricer 함수(BOW 기반 예측)를 테스트에 적용
# - 테스트셋 250개 아이템에 대해 가격 예측 수행
# - 예측값과 실제값을 비교하여:
#   • 오차(Error)
#   • 로그 오차 제곱(RMSLE)
#   • 정확도(Hits)
#   등을 자동으로 계산 및 출력
# - 예측 vs 실제 가격을 시각화한 산점도도 함께 생성됨

🧠 이 평가를 통해 텍스트 설명만으로 가격을 얼마나 정확히 예측할 수 있는지 확인할 수 있어요.

기존 선형 회귀 기반 수치형 특성 모델과의 비교도 흥미로운 포인트입니다.


🧠 9. Word2Vec 기반 회귀 모델

Word2Vec 임베딩 모델 학습 (gensim 사용)

이제 단순 BOW를 넘어서, 단어의 의미와 문맥까지 반영할 수 있는 Word2Vec 모델을 사용합니다.

# 🌟 놀라운 Word2Vec 모델! (gensim NLP 라이브러리 활용)

np.random.seed(42)
# 🔒 랜덤 시드 고정 → 동일한 임베딩 결과 재현 가능

# 🧼 문서 전처리: 토큰화 및 소문자화
processed_docs = [simple_preprocess(doc) for doc in documents]
# - 각 문서를 단어 단위로 분해 (소문자 + 특수문자 제거 + 토큰화)
# - 예: "This is great!" → ['this', 'is', 'great']

# 🧠 Word2Vec 모델 학습
w2v_model = Word2Vec(
    sentences=processed_docs,   # 📚 학습 문서 (토큰화된 리스트들)
    vector_size=400,            # 📐 단어 벡터의 차원 수 (400차원 벡터로 표현)
    window=5,                   # 👀 윈도우 크기: 주변 5단어까지 문맥으로 고려
    min_count=1,                # 📉 최소 등장 횟수: 1 이상인 단어만 학습에 사용
    workers=8                   # ⚙️ 멀티코어 CPU 병렬처리 (속도 향상)
)

🧠 이 모델은 단어들을 벡터 공간에 매핑하고, 비슷한 의미를 가진 단어들을 가깝게 위치시켜 줍니다.

📄 Word2Vec 기반 문서 벡터 생성 (평균 임베딩 방식)

아래는 Word2Vec 기반 문서 임베딩을 생성하는 코드이며,

문서 내 단어 벡터들의 평균값을 사용해 전체 문서를 벡터로 표현하는 방식이에요.

(※ 단, 이 방식은 문맥 순서나 중요도 정보가 손실되는 약점이 있습니다!)

# 📉 문서 벡터화: 문서 내 단어들의 벡터 평균을 사용
# ⚠️ 참고: 이 방식은 문맥/위치 정보가 사라지는 단점이 있음

def document_vector(doc):
    doc_words = simple_preprocess(doc)
    # 🧼 입력 문서를 단어 리스트로 전처리 (소문자 + 토큰화)

    word_vectors = [w2v_model.wv[word] for word in doc_words if word in w2v_model.wv]
    # 🧠 문서에 포함된 각 단어에 대해 Word2Vec 벡터를 가져옴
    # - 존재하지 않는 단어는 무시

    return np.mean(word_vectors, axis=0) if word_vectors else np.zeros(w2v_model.vector_size)
    # 📐 단어 벡터들의 평균값을 문서 벡터로 사용
    # - 단어가 하나도 없을 경우, 0벡터로 처리
# 🧾 문서 임베딩 행렬 생성 (각 문서 → 400차원 벡터)

X_w2v = np.array([document_vector(doc) for doc in documents])
# - 학습 데이터의 각 문서를 Word2Vec 벡터로 변환
# - 결과: (문서 수 × 400차원) 형태의 numpy 배열

🧠 이 벡터들은 이제 머신러닝 모델의 입력값으로 사용할 수 있습니다.

📈 Word2Vec 기반 회귀 모델 학습

앞에서 만든 문서 벡터를 이용해 가격을 예측하는 모델을 학습하는 단계예요.

# 📈 Word2Vec 기반 문서 벡터에 선형 회귀 모델 적용

word2vec_lr_regressor = LinearRegression()
# 🤖 선형 회귀 모델 객체 생성

word2vec_lr_regressor.fit(X_w2v, prices)
# 🧠 문서 임베딩 벡터(X_w2v)를 입력으로,
# 💰 실제 가격(prices)을 타깃으로 하여 모델 학습
# - 각 단어 벡터의 평균값으로 구성된 문서 벡터를 기반으로 가격 예측 모델을 만듦

이 모델은 문서에 담긴 의미 기반 정보(Word2Vec 벡터)를 활용해 가격을 예측하려는 시도이며,
기존 BOW보다 더 정교한 예측이 가능할 수도 있습니다.

🧠 Word2Vec + 선형 회귀 기반 가격 예측 함수 정의

이 함수는 Word2Vec 벡터 + 선형 회귀 모델을 활용해 새로운 아이템의 가격을 예측합니다.

# 🧠 Word2Vec + 선형 회귀 기반 가격 예측 함수

def word2vec_lr_pricer(item):
    doc = item.test_prompt()
    # 📝 아이템의 프롬프트(설명 텍스트)를 가져옴
    # - 반드시 test_prompt() 사용 → 정답 유출 방지

    doc_vector = document_vector(doc)
    # 📐 문서 내 단어들을 평균 임베딩하여 400차원 문서 벡터 생성

    return max(0, word2vec_lr_regressor.predict([doc_vector])[0])
    # 🤖 학습된 선형 회귀 모델을 이용해 가격 예측 수행
    # - 예측값이 0보다 작을 경우, 0으로 보정 (음수 가격 방지)

이 함수는 Word2Vec이 제공하는 의미적 정보를 바탕으로 한 가격 예측을 실험하기 위한 모델입니다.
BOW나 수치형 피처 기반 모델보다 더 나은 성능을 낼 수 있는지 평가해 볼 수 있어요.

🧪 Word2Vec 기반 모델 성능 테스트

Word2Vec + 선형 회귀 기반 모델의 성능을 테스트 셋 전체에 걸쳐 평가하는 단계입니다.

# 🧪 Word2Vec + 선형 회귀 모델 성능 평가 실행

Tester.test(word2vec_lr_pricer)
# - word2vec_lr_pricer 함수(Word2Vec 벡터 기반 예측)를 테스트 실행기에 전달
# - 테스트셋의 250개 아이템에 대해:
#   • 가격 예측 수행
#   • 실제 가격과의 오차 계산
#   • SLE, RMSLE, 평균 오차, 정확도(Hits) 등 출력
# - 예측 vs 실제 가격 산점도 그래프 자동 생성

이 평가를 통해 "의미 기반 텍스트 표현"이
기존의 BOW나 수치형 피처 기반 모델보다 더 나은지 확인할 수 있어요.


⚙️ 10. SVR (Support Vector Regression) 실험

Word2Vec 기반 선형 서포트 벡터 회귀 모델 학습

이제 Word2Vec 벡터를 입력으로 사용하는 또 다른 전통 ML 모델, 서포트 벡터 머신 회귀(SVM)를 실험해 봅니다.

# ⚙️ 서포트 벡터 회귀(SVR) 모델 적용 (Word2Vec 벡터 기반)

np.random.seed(42)
# 🔒 재현 가능한 결과를 위해 랜덤 시드 고정

svr_regressor = LinearSVR()
# 🤖 선형 서포트 벡터 회귀 모델 객체 생성
# - SVM 기반의 회귀 모델
# - 이상치에 더 강하고, 고차원 데이터에도 잘 작동하는 특징이 있음

svr_regressor.fit(X_w2v, prices)
# 🧠 문서 벡터(X_w2v)를 입력으로, 실제 가격(prices)을 타깃으로 하여 모델 학습 수행

LinearSVR은 선형 회귀보다 더 강건한(robust) 대안이며, 특히 노이즈나 극단값이 있는 경우에 더 안정적인 결과를 낼 수 있습니다.

Word2Vec + SVM 기반 가격 예측 함수 정의

Word2Vec 벡터 + 선형 SVM 회귀 모델을 사용하여 새로운 아이템의 가격을 예측하는 함수입니다:

# ⚙️ Word2Vec + 선형 서포트 벡터 회귀 기반 가격 예측 함수

def svr_pricer(item):
    np.random.seed(42)
    # 🔒 매 예측 시 동일한 결과를 얻기 위해 랜덤 시드 고정 (안정성 확보용)

    doc = item.test_prompt()
    # 📝 입력 아이템의 설명 텍스트 가져오기 (정답 유출 방지를 위해 test_prompt 사용)

    doc_vector = document_vector(doc)
    # 📐 해당 문서를 Word2Vec을 이용해 400차원 벡터로 변환

    return max(float(svr_regressor.predict([doc_vector])[0]), 0)
    # 🤖 학습된 SVR 모델로 가격 예측 수행
    # - 결과가 0보다 작을 경우 0으로 보정 (음수 가격 방지)
    # - float으로 형 변환하여 결과 값 명확히 반환

🧠 이 모델은 선형 회귀보다 극단값에 더 강한 예측 모델이며,
Word2Vec의 의미 기반 표현력을 그대로 활용해 텍스트만으로 가격을 예측합니다.

🧪 Word2Vec + SVR 모델 성능 테스트

Word2Vec + 서포트 벡터 회귀(SVR) 모델의 실제 성능을 테스트 셋에 적용하여 평가하는 단계입니다.

# 🧪 Word2Vec + SVR 모델 성능 평가 실행

Tester.test(svr_pricer)
# - svr_pricer 함수(Word2Vec 벡터 기반 SVM 회귀 예측)를 테스트셋에 적용
# - 총 250개의 테스트 아이템에 대해 가격을 예측하고,
#   예측값과 실제값의 차이를 기준으로 다음 항목들을 자동 계산:
#   • 평균 오차 (Error)
#   • RMSLE (로그 스케일 오차)
#   • 정확도(Hits, 예측이 괜찮았던 비율)
# - 결과는 콘솔에 출력되고,
#   예측값 vs 실제값을 시각화한 산점도 그래프도 함께 표시됨

🧠 이 단계는 모델의 실제 예측력이 어떤지,

기존 BOW나 선형 회귀 모델보다 더 나은 성능을 발휘하는지 평가하는 핵심 실험입니다.


🌳 11. Random Forest 회귀 모델 실험

Word2Vec 기반 랜덤 포레스트 회귀 모델 학습

랜덤 포레스트는 다양한 결정 트리들의 예측을 평균 내어 강력하고 안정적인 예측을 수행하는 앙상블 모델입니다.

# 🌳 강력한 랜덤 포레스트 회귀 모델 학습

rf_model = RandomForestRegressor(
    n_estimators=100,      # 🌲 사용할 결정 트리(tree)의 개수 (100개)
    random_state=42,       # 🔒 재현 가능한 결과를 위한 랜덤 시드 고정
    n_jobs=8               # ⚙️ 병렬 처리에 사용할 CPU 코어 수 (최대 8개 사용)
)

rf_model.fit(X_w2v, prices)
# 🧠 Word2Vec 벡터(X_w2v)를 입력, 실제 가격(prices)을 타깃으로 하여 모델 학습 수행
# - 여러 개의 결정 트리를 학습하여 예측 결과를 평균냄
# - 복잡한 비선형 관계도 잘 학습함

🧠 랜덤 포레스트는 과적합에 강하고, 특성 간 비선형 상호작용을 잘 포착할 수 있어서
실제 문제에서 자주 사용하는 강력한 회귀 모델입니다.

Word2Vec + 랜덤 포레스트 기반 가격 예측 함수 정의

Word2Vec 벡터를 기반으로 랜덤 포레스트 회귀 모델을 통해 가격을 예측하는 함수입니다.

# 🌳 Word2Vec + 랜덤 포레스트 기반 가격 예측 함수

def random_forest_pricer(item):
    doc = item.test_prompt()
    # 📝 입력 아이템의 설명 텍스트 추출 (test_prompt 사용 → 정답 유출 방지)

    doc_vector = document_vector(doc)
    # 📐 텍스트를 Word2Vec 기반 벡터(400차원)로 변환

    return max(0, rf_model.predict([doc_vector])[0])
    # 🤖 학습된 랜덤 포레스트 모델로 가격 예측 수행
    # - 결과가 0보다 작을 경우 0으로 보정 (음수 가격 방지)

🧠 이 함수는 Word2Vec의 의미 기반 표현랜덤 포레스트의 강력한 예측 성능을 결합한 모델로,
텍스트 기반 가격 예측에서 매우 경쟁력 있는 모델이 될 수 있습니다.

🧪 Word2Vec + 랜덤 포레스트 모델 성능 테스트

Word2Vec + 랜덤 포레스트 모델의 성능을 테스트 셋 전체에 대해 평가하는 단계입니다:

# 🧪 Word2Vec + 랜덤 포레스트 모델 성능 평가 실행

Tester.test(random_forest_pricer)
# - random_forest_pricer 함수(RandomForest 기반 가격 예측)를 테스트셋에 적용
# - 테스트 데이터 250개에 대해 다음 항목들을 자동 평가:
#   • 예측값 vs 실제값 출력
#   • 오차(Error), SLE, RMSLE 계산
#   • 정확도(Hits, 좋은 예측의 비율)
# - 예측 결과를 시각화한 산점도 그래프도 함께 표시

이 테스트는 지금까지 실험한 모델들 중
가장 강력한 성능을 낼 수 있는 앙상블 모델의 성과를 확인하는 매우 중요한 평가입니다.

반응형