DEV Community

Fennikz
Fennikz

Posted on

การทำระบบเเนะนำหนังสือ โดยใช้ K-Nearest Neighbors

บทความนี้จะเป็นการทดลองการสร้างระบบเเนะนำหนังสือที่มีอยู่ในชุดข้อมูลหนังสือโดยจะใช้ K-Nearest Neighbors หรือ KNN เพื่อเเนะนำหนังสือที่คล้ายกัน

K-Nearest Neighbors ถือเป็น Supervised Machine Learning Algorithm ใช้ในการจัดหมวดหมู่หรือการถดถอย

ซึ่งทำงานได้โดยการกำหนดค่า K ซึ่งก็คือจำนวน Training Samples ที่มีระยะทางใกล้กับ Data Point ใหม่มากที่สุดและทำนายจาก Majority ของ K samples เหล่านั้น


ขั้นตอนการทำ

ขั้นที่ 1 : นำเข้า Libraries ที่ต้องใช้ทั้งหมดลงใน Google Colab

import numpy as np
import pandas as pd
from scipy.sparse import csr_matrix
from sklearn.neighbors import NearestNeighbors
import matplotlib.pyplot as plt

import warnings
warnings.filterwarnings('ignore')
pd.set_option('display.max_colwidth', None)

import os, sys
import re
Enter fullscreen mode Exit fullscreen mode

ขั้นที่ 2 : โหลด dataset : books

โดยตัวข้อมูลจะอยู่ใน folder data ซึ่งสามารถเรียกใช้ โดยทำการเขียนชื่อ folder/ชื่อไฟล์
Image description

ดาวน์โหลด dataset ตัวอย่าง --> HERE

Code ดาวน์โหลดข้อมูล

df_books = pd.read_csv('data/Books.csv')
df_books.head()
Enter fullscreen mode Exit fullscreen mode

Image description

ขั้นที่ 3 : ตรวจสอบชื่อคอลัมน์

แสดงรายชื่อคอลัมน์ทั้งหมดใน DataFrame df_books

df_books.columns
Enter fullscreen mode Exit fullscreen mode

Image description

ขั้นที่ 4 : ลบคอลัมน์ที่ไม่ต้องการออก

df_books = df_books[['ISBN', 'Book-Title', 'Book-Author']]
Enter fullscreen mode Exit fullscreen mode

ขั้นที่ 5 : โหลด dataset : ratings

ดาวน์โหลด dataset ตัวอย่าง --> HERE
Code ดาวน์โหลดข้อมูล

df_ratings = pd.read_csv('data/Ratings.csv')
df_ratings.head()
Enter fullscreen mode Exit fullscreen mode

Image description

ขั้นที่ 6 : ตรวจสอบค่า Null

นับจำนวนของค่า null หรือ missing values ในแต่ละคอลัมน์ของ DataFrame และแสดงผลรวมของค่า null ในแต่ละคอลัมน์ซึ่งจะมีประโยชน์ในการตรวจสอบความสมบูรณ์ของข้อมูลหรือการจัดการกับค่าที่ขาดหายไปใน DataFrame.

df_books.isnull().sum()
Enter fullscreen mode Exit fullscreen mode

Image description

df_ratings.isnull().sum()
Enter fullscreen mode Exit fullscreen mode

Image description

ขั้นที่ 7 : ดรอปค่า Null

ลบแถวที่มีค่า null (หรือ missing values) ออกจาก DataFrame

df_books.dropna(inplace=True)
df_books.isnull().sum()
Enter fullscreen mode Exit fullscreen mode

Image description

ขั้นที่ 8 : ตรวจสอบขนาดของ Dataset

df_books.shape
Enter fullscreen mode Exit fullscreen mode

จะได้ output ออกมาเป็น tuple ที่มีสมาชิกสองตัวเป็น (จำนวนแถว, จำนวนคอลัมน์)
Image description

df_ratings.shape
Enter fullscreen mode Exit fullscreen mode

Image description

ขั้นที่ 9 : เรียงลำดับการให้คะเเนน

# Calculate the count of ratings given by each user and store it in the 'ratings' Series
ratings = df_ratings['User-ID'].value_counts()
# Sort the 'ratings' Series in descending order based on the counts of user IDs
ratings.sort_values(ascending=False).head()
Enter fullscreen mode Exit fullscreen mode

Image description

ขั้นที่ 10 : ตรวจสอบผู้ใช้ที่มีคะเเนนน้อยกว่า 200

len(ratings[ratings < 200])
Enter fullscreen mode Exit fullscreen mode

Image description

df_ratings['User-ID'].isin(ratings[ratings < 200].index).sum()
Enter fullscreen mode Exit fullscreen mode

Image description

df_ratings_rm = df_ratings[
  ~df_ratings['User-ID'].isin(ratings[ratings < 200].index)
]
df_ratings_rm.shape
Enter fullscreen mode Exit fullscreen mode

Image description

ขั้นที่ 11 : ตรวจสอบหนังสือที่มีคะเเนนน้อยกว่า 100

ratings = df_ratings['ISBN'].value_counts() 
ratings.sort_values(ascending=False).head()
Enter fullscreen mode Exit fullscreen mode

Image description

len(ratings[ratings < 100])
Enter fullscreen mode Exit fullscreen mode

Image description

df_books['ISBN'].isin(ratings[ratings < 100].index).sum()
Enter fullscreen mode Exit fullscreen mode

Image description

df_ratings_rm = df_ratings_rm[
  ~df_ratings_rm['ISBN'].isin(ratings[ratings < 100].index)
]
df_ratings_rm.shape
Enter fullscreen mode Exit fullscreen mode

Image description

# These should exist
books = ["Where the Heart Is (Oprah's Book Club (Paperback))",
        "I'll Be Seeing You",
        "The Weight of Water",
        "The Surgeon",
        "I Know This Much Is True"]

for book in books:
    print(df_ratings_rm['ISBN'].isin(df_books[df_books['Book-Title'] == book]['ISBN']).sum())
Enter fullscreen mode Exit fullscreen mode

Image description

ขั้นที่ 12 : ประมวลผลชุดข้อมูลล่วงหน้าสำหรับ Machine LearningMachine Learning

แสดงผลลัพธ์ของ DataFrame df_ratings_rm

df_ratings_rm.head()
Enter fullscreen mode Exit fullscreen mode

Image description

แสดงผลลัพธ์ของ DataFrame df_books

df_books.head()
Enter fullscreen mode Exit fullscreen mode

Image description

สร้างตารางเชิงกระจาย (pivot table) จาก DataFrame df_ratings_rm โดยให้ 'User-ID' เป็น index และ 'ISBN' เป็น columns และ 'Book-Rating' เป็นค่าที่ใช้ในการเปลี่ยนรูปแบบของตารางโดยใช้ code ดังนี้

df = df_ratings_rm.pivot_table(index=['User-ID'],columns=['ISBN'],values='Book-Rating').fillna(0).T
df.head()
Enter fullscreen mode Exit fullscreen mode

Image description

df.indexคือการที่นำ DataFrame df กับ DataFrame df_books มารวมกันซึ่งทำให้เราสามารถเข้าถึงข้อมูลหนังสือได้โดยอ้างอิงชื่อของหนังสือแทนที่จะอ้างอิงด้วย ISBN โดยใช้ code ดังนี้

df.index = df.join(df_books.set_index('ISBN'))['Book-Title']
Enter fullscreen mode Exit fullscreen mode

ทำการเรียงลำดับแถวของ DataFrame df ตาม index(ชื่อของหนังสือ) ให้เรียงลำดับตามตัวอักษรโดยใช้ code ดังนี้

df = df.sort_index()
df.head()
Enter fullscreen mode Exit fullscreen mode

Image description

แสดงคะแนนการจัดอันดับของหนังสือโดยใช้หนังสือตัวอย่างคือหนังสือ "The Queen of the Damned (Vampire Chronicles (Paperback))" โดยใช้ code ดังนี้

df.loc["The Queen of the Damned (Vampire Chronicles (Paperback))"][:5]
Enter fullscreen mode Exit fullscreen mode

ซึ่งจะเเสดง 5 คอลัมน์แรกใน DataFrame df ออกมาเป็นข้อมูลดังนี้:

Image description


สร้างเเบบจำลอง K-Nearest Neighbors

model = NearestNeighbors(metric='cosine')
model.fit(df.values)
Enter fullscreen mode Exit fullscreen mode

Image description

df.iloc[0].shape
Enter fullscreen mode Exit fullscreen mode

Image description

title = 'The Queen of the Damned (Vampire Chronicles (Paperback))'
df.loc[title].shape
Enter fullscreen mode Exit fullscreen mode

Image description

distance, indice = model.kneighbors([df.loc[title].values], n_neighbors=6)

print(distance)
print(indice)
Enter fullscreen mode Exit fullscreen mode

Image description

df.iloc[indice[0]].index.values
Enter fullscreen mode Exit fullscreen mode

Image description

pd.DataFrame({
    'title'   : df.iloc[indice[0]].index.values,
    'distance': distance[0]
}) \
.sort_values(by='distance', ascending=False)
Enter fullscreen mode Exit fullscreen mode

Image description


สร้างฟังก์ชันค้นหาหนังสือแนะนำจากหนังสือที่ input ลงไป

# function to return recommended books - this will be tested
def get_recommends(title = ""):
  try:
    book = df.loc[title]
  except KeyError as e:
    print('The given book', e, 'does not exist')
    return

  distance, indice = model.kneighbors([book.values], n_neighbors=6)

  recommended_books = pd.DataFrame({
      'title'   : df.iloc[indice[0]].index.values,
      'distance': distance[0]
    }) \
    .sort_values(by='distance', ascending=False) \
    .head(5).values

  return [title, recommended_books]
Enter fullscreen mode Exit fullscreen mode

การใช้งานระบบเเนะนำหนังสือ

1.ลองทดลองระบบเเนะนำหนังสือโดยใช้หนังสือ The Queen of the Damned (Vampire Chronicles (Paperback))

Image description

books = get_recommends("The Queen of the Damned (Vampire Chronicles (Paperback))")
print(books)
Enter fullscreen mode Exit fullscreen mode

ผลลัพธ์ที่ได้ :
Image description

2.ทดลองระบบเเนะนำหนังสือโดยใช้หนังสือที่ไม่มีใน dataset

books = get_recommends("Dreamsnake")
print(books)
Enter fullscreen mode Exit fullscreen mode

ผลลัพธ์ที่ได้ :
Image description

สรุปผล

จากการทำลองใช้งานระบบเเนะนำหนังสือจะเห็นได้ว่าถ้าเรา input หนังสือที่มีอยู่ใน data เเละให้ระบบเเนะนำหนังสือให้ระบบก็จะเเนะนำหนังสือที่มีความคล้ายคลึงกันที่อยู่ใน data ออกมาให้ 5 เล่ม เเต่ถ้าหนังสือที่เรา input เข้าไปไม่อยู่ใน data ระบบก็จะขึ้นเตือนว่า The given book '...' does not exist

ขอขอบคุณข้อมูลจาก

Top comments (0)