0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

MovieLensで学ぶレコメンドシステム入門(User-based Collaborative Filtering)

Posted at

概要

  • 目的:協調フィルタリング(User-based CF)の仕組みをPythonで理解し、教育分野でのパーソナライズ学習への応用を探る
  • 手法:MovieLensデータセットを用い、ユーザー間コサイン類似度とMAEで評価
  • 学び:レコメンドは単なるアルゴリズムではなく、学習支援や教材最適化の基盤になり得る

はじめに

業務でレコメンドを扱うことはありませんが、
生徒の探究活動の中で「レコメンドの仕組み」について研究している生徒がいたため、
私自身も理解を深める目的で学んでみることにしました。

データ分析や教育分野では「パーソナライズ」がキーワードになることも多く、
この分野の基礎を押さえておくことは今後の教育DXにも役立つと考えています。
今回は、教育現場での探究にも応用できそうなレコメンドの基本原理を、
Pythonと公開データセットを使って実装しました。


目的

  • MovieLensデータセットを用いて、**協調フィルタリング(User-based CF)**の仕組みを理解する
  • コサイン類似度によってユーザー間の嗜好の近さを計算し、映画評価を予測する
  • 教育分野における「レコメンド思考」の応用を考える

使用データ

  • MovieLens Dataset - 100K (Kaggle)
    → 映画の評価履歴データ(userId, movieId, rating など)

実装コード

# ==============================================
# MovieLensによるレコメンドシステム入門
# 協調フィルタリング(User-based)
# ==============================================

import pandas as pd
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity
from sklearn.metrics import mean_absolute_error
import matplotlib.pyplot as plt

# --- 1. データ読み込み(MovieLens 100k) ---
ratings = pd.read_csv("ratings.csv")
movies = pd.read_csv("movies.csv")

# --- 2. 行列化(ユーザー×映画) ---
rating_matrix = ratings.pivot_table(index="userId", columns="movieId", values="rating")
print(f"データ行列サイズ: {rating_matrix.shape}")

# --- 3. 類似度計算(ユーザー間コサイン類似度) ---
rating_filled = rating_matrix.fillna(0)
user_similarity = cosine_similarity(rating_filled)
user_sim_df = pd.DataFrame(user_similarity, index=rating_matrix.index, columns=rating_matrix.index)

# --- 4. レコメンド関数(類似ユーザーから予測) ---
def predict_rating(user_id, movie_id, k=5):
    similar_users = user_sim_df[user_id].sort_values(ascending=False)[1:k+1].index
    sim_scores = user_sim_df.loc[similar_users, user_id]
    movie_ratings = rating_matrix.loc[similar_users, movie_id]
    return np.dot(movie_ratings.fillna(0), sim_scores) / sim_scores.sum()

# --- 5. 検証データを作成して精度確認 ---
sample = ratings.sample(500, random_state=42)
preds = []
for _, row in sample.iterrows():
    try:
        preds.append(predict_rating(row.userId, row.movieId))
    except:
        preds.append(np.nan)

sample["pred"] = preds
sample = sample.dropna()
mae = mean_absolute_error(sample["rating"], sample["pred"])
print(f"\n平均絶対誤差(MAE) = {mae:.3f}")

# --- 6. 実際のおすすめ映画を表示(例:ユーザー1) ---
target_user = 1
user_seen = ratings[ratings["userId"] == target_user]["movieId"].tolist()
user_unseen = [m for m in rating_matrix.columns if m not in user_seen]

pred_scores = {m: predict_rating(target_user, m) for m in user_unseen}
recommend_df = pd.DataFrame(list(pred_scores.items()), columns=["movieId", "pred_score"])
top_movies = recommend_df.merge(movies, on="movieId").sort_values("pred_score", ascending=False).head(5)

print("\n=== ユーザー1へのおすすめ映画 ===")
print(top_movies[["title", "pred_score"]])

# --- 7. 可視化 ---
plt.hist(sample["rating"] - sample["pred"], bins=20, color="skyblue", edgecolor="k")
plt.title("予測誤差の分布(実際−予測)")
plt.xlabel("誤差")
plt.ylabel("頻度")
plt.show()

結果例

image.png

image.png

...
MAEが2.086というのは、予測誤差が2.0〜2.1点程度という意味です。
映画の評価は主観的な要素が大きいため、精度がどこまでよくなるのか興味があります。

分析の要点

ステップ 内容 学べること
ユーザー×映画の行列を作る データの構造を意識した前処理
コサイン類似度を使う ユーザーの嗜好パターンを数値化
類似ユーザーから重み付き平均 協調フィルタリングの核心
MAEで評価 モデルの性能を客観的に測定

学びと今後

レコメンドは「似ている人が好きなものを薦める」シンプルな仕組みから始まりますが、
この背後には「ベクトル」「類似度」「重み付け平均」など、
数学・統計・機械学習の基本が詰まっています。

生徒の探究活動を支援する立場として、
こうしたアルゴリズムを理解しておくことで、
「AIがどうやっておすすめしているのか?」を正しく説明できるようになるのは大きな収穫でした。

教育への応用を考えて

現時点では、これを直接授業で活用する予定はありませんが、
「生徒の探究テーマを支援するために、自分も一緒に学ぶ」 という姿勢はとても大切だと感じました。
教育データや学習履歴を用いたパーソナライズ学習にも応用可能な考え方であり、
今後どのように教育に生かせるか模索していきたいと思います。
例えば、教育プラットフォーム上で生徒の学習履歴を用いたレコメンドモデル(教材・学習順序・学習仲間など)への応用を検討しています。
また、ユーザー体験を最適化するために、協調フィルタリングと深層学習ベースのハイブリッド化も視野に入れています。

「AIの中身を“使う側”ではなく、“理解する側”へ」
その第一歩として、レコメンドを実装してみました。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?