天天看點

python 處理 MovieLens 資料一、總述二、處理流程

文章目錄

  • 一、總述
  • 二、處理流程
    • 1. 處理 users 資料
    • 2. 處理 movies 資料
    • 3. 處理 ratings 資料
    • 4. 将 users、movies 和 ratings 資料合并
    • 5. one-hot 處理
    • 6. 完整代碼

一、總述

該文記錄處理 MovieLens-1m 資料集的步驟,首先分别處理使用者、電影和評分資料,接着将這三部分資料進行合并,最後 one-hot 處理。

二、處理流程

1. 處理 users 資料

users 資料描述:

使用者檔案有以下字段,分别是使用者ID、性别、年齡、職業和郵編( UserID::Gender::Age::Occupation::Zip-code )

處理思路:

  • 将使用者性别 M、F 進行 label encoding 編碼
  • 将年齡 label encoding 編碼
  • 郵編取前3位

代碼:

# 處理使用者
users = pd.read_table('../../dataset/ml-1m/users.dat', sep='::', header=None, engine='python', encoding='utf-8').to_numpy()

# 處理使用者年齡和郵編
le = LabelEncoder()
users[:, 1] = le.fit_transform(users[:, 1]) # 将性别 label Encoding

for user in users:  # 将年齡 Lable Encoding
    if user[2] == 1:
        user[2] = 0
    elif user[2] == 18:
        user[2] = 1 
    elif user[2] == 25:
        user[2] = 2
    elif user[2] == 35:
        user[2] = 3
    elif user[2] == 45:
        user[2] = 4
    elif user[2] == 50:
        user[2] = 5
    elif user[2] == 56:
        user[2] = 6
    user[4] = int(user[4][0:3]) - 1 # 取郵編的前3位
    user[0] -= 1 // 從 0 開始
           

users 處理結果:

python 處理 MovieLens 資料一、總述二、處理流程

2. 處理 movies 資料

movies 資料描述:

電影檔案包含三個字段,分别是電影ID、電影名、電影類型( MovieID::Title::Genres )

處理思路:

将電影名稱删除,電影類型在合并users、movies和ratings之後做 one-hot 處理。

代碼:

# 處理電影
movies = pd.read_table('../../dataset/ml-1m/movies.dat', sep='::', header=None, engine='python', encoding='ISO-8859-1').to_numpy()
movies = np.delete(movies, 1, axis=1) # 删除電影名稱列  
movies[:, 0] -= 1
           

movies 處理結果:

python 處理 MovieLens 資料一、總述二、處理流程

3. 處理 ratings 資料

ratings 資料描述:

電影評分檔案包含使用者ID、電影ID、評分和時間戳( UserID::MovieID::Rating::Timestamp )

處理思路:

  • 将時間戳字段删除
  • 将評分大于3的作為正樣本(記為1),評分小于等于3的作為負樣本(記為0)

代碼:

# 處理使用者評分
ratings = pd.read_table('../../dataset/ml-1m/ratings.dat', sep='::', header=None, engine='python', encoding='utf-8').to_numpy()[:, :3]
ratings[:, 0:2] -= 1

for i in range(len(ratings)):
    ratings[i][2] = 1 if ratings[i][2] > 3 else 0
           

4. 将 users、movies 和 ratings 資料合并

代碼:

unames = ['userId', 'gender', 'age', 'occupation', 'zipCode']
mnames = ['movieId', 'genres']
rnames = ['userId', 'movieId', 'rating']

users = pd.DataFrame(users, columns=unames)
movies = pd.DataFrame(movies, columns=mnames)
ratings = pd.DataFrame(ratings, columns=rnames)

data = pd.merge(movies, ratings, on=['movieId'])
data = pd.merge(users, data, on=['userId'])
           

資料合并結果:

python 處理 MovieLens 資料一、總述二、處理流程

5. one-hot 處理

處理思路:

  • 将電影類型單獨手動 one-hot 處理
  • 然後将 data 中的電影類型删除,再做 one-hot 處理

代碼:

data = data.values // dataframe 轉 numpy
y = data[:, 7]
x = np.delete(data, -1, axis=1) # 将評分列删除
typelist = x[:, -1]
x = np.delete(x, -1, axis=1)    # 将電影類型列删除

# 将電影類型 one-hot 編碼
genres = [] # 電影類型 ont-hot 編碼
genresDict = {'Action' : 0, 'Adventure' : 1, 'Animation' : 2, "Children's" : 3, 'Comedy' : 4, 'Crime' : 5, 'Documentary' : 6, 
            'Drama' : 7, 'Fantasy' : 8, 'Film-Noir' : 9, 'Horror' : 10, 'Musical' : 11, 'Mystery' : 12, 'Romance' : 13, 
            'Sci-Fi' : 14, 'Thriller' : 15, 'War' : 16, 'Western' : 17
            }
for types in typelist:
    strs = types.split('|')
    tmp = np.zeros(18)
    for str in strs:
        tmp[genresDict[str]] = 1
    genres.append(tmp)
genres = np.array(genres)

# 将 userId, gender, age, occupation, zipCode, movieId one-hot 編碼
encoder = OneHotEncoder(handle_unknown='ignore')
x = encoder.fit_transform(x).toarray()
x = np.concatenate((x, genres),axis=1)
           

x one-hot 結果:

python 處理 MovieLens 資料一、總述二、處理流程

y one-hot 結果:

python 處理 MovieLens 資料一、總述二、處理流程

6. 完整代碼

import numpy as np
import pandas as pd
from sklearn.preprocessing import OneHotEncoder, LabelEncoder

# 處理使用者
users = pd.read_table('../../dataset/ml-1m/users.dat', sep='::', header=None, engine='python', encoding='utf-8').to_numpy()

# 處理使用者年齡和郵編
le = LabelEncoder()
users[:, 1] = le.fit_transform(users[:, 1]) # 将性别 label Encoding

for user in users:  # 将年齡 Lable Encoding
    if user[2] == 1:
        user[2] = 0
    elif user[2] == 18:
        user[2] = 1 
    elif user[2] == 25:
        user[2] = 2
    elif user[2] == 35:
        user[2] = 3
    elif user[2] == 45:
        user[2] = 4
    elif user[2] == 50:
        user[2] = 5
    elif user[2] == 56:
        user[2] = 6
    user[4] = int(user[4][0:3]) - 1 # 取郵編的前3位
    user[0] -= 1
    
# 處理電影
movies = pd.read_table('../../dataset/ml-1m/movies.dat', sep='::', header=None, engine='python', encoding='ISO-8859-1').to_numpy()
movies = np.delete(movies, 1, axis=1) # 删除電影名稱列  
movies[:, 0] -= 1

# 處理使用者評分
ratings = pd.read_table('../../dataset/ml-1m/ratings.dat', sep='::', header=None, engine='python', encoding='utf-8').to_numpy()[:, :3]
ratings[:, 0:2] -= 1

for i in range(len(ratings)):
    ratings[i][2] = 1 if ratings[i][2] > 3 else 0

unames = ['userId', 'gender', 'age', 'occupation', 'zipCode']
mnames = ['movieId', 'genres']
rnames = ['userId', 'movieId', 'rating']
users = pd.DataFrame(users, columns=unames)
movies = pd.DataFrame(movies, columns=mnames)
ratings = pd.DataFrame(ratings, columns=rnames)
data = pd.merge(movies, ratings, on=['movieId'])
data = pd.merge(users, data, on=['userId'])

data = data.values
y = data[:, 7]
x = np.delete(data, -1, axis=1) # 将評分列删除
typelist = x[:, -1]
x = np.delete(x, -1, axis=1)    # 将電影類型列删除

# 将電影類型 one-hot 編碼
genres = [] # 電影類型 one-hot 編碼
genresDict = {'Action' : 0, 'Adventure' : 1, 'Animation' : 2, "Children's" : 3, 'Comedy' : 4, 'Crime' : 5, 'Documentary' : 6, 
            'Drama' : 7, 'Fantasy' : 8, 'Film-Noir' : 9, 'Horror' : 10, 'Musical' : 11, 'Mystery' : 12, 'Romance' : 13, 
            'Sci-Fi' : 14, 'Thriller' : 15, 'War' : 16, 'Western' : 17
            }
for types in typelist:
    strs = types.split('|')
    tmp = np.zeros(18)
    for str in strs:
        tmp[genresDict[str]] = 1
    genres.append(tmp)
genres = np.array(genres)

# 将 userId, gender, age, occupation, zipCode, movieId one-hot 編碼
encoder = OneHotEncoder(handle_unknown='ignore')
x = encoder.fit_transform(x).toarray()
x = np.concatenate((x, genres),axis=1)
           

繼續閱讀