對load的資料進行資料預處理,比如去除電影名中的年份、將使用者性別用0-1表示、使用者年齡段用0~6來表示等等
資料預處理
- UserID、Occupation和MovieID不用變。
- Gender欄位:需要將‘F’和‘M’轉換成0和1。
- Age欄位:要轉成7個連續數字0~6。
- Genres欄位:是分類欄位,要轉成數字。首先將Genres中的類別轉成字串到數字的字典,然後再將每個電影的Genres欄位轉成數字列表,因為有些電影是多個Genres的組合。
- Title欄位:處理方式跟Genres欄位一樣,首先建立文字到數字的字典,然後將Title中的描述轉成數字的列表。另外Title中的年份也需要去掉。
- Genres和Title欄位需要將長度統一,這樣在神經網路中方便處理。空白部分用‘< PAD >’對應的數字填充。
構建資料處理的物件,預設初始化,三個資料集的路徑,方便呼叫訪問:
class MovieRecommend():
def __init__(self):
self.UserDataPath = './ml-1m/users.dat'
self.MoviesDataPath = './ml-1m/movies.dat'
self.RatingsDataPath = './,1-1m/ratings.dat'
對使用者資料進行預處理
如上
- Gender欄位:需要將‘F’和‘M’轉換成0和1。
- Age欄位:要轉成7個連續數字0~6。
def load_user_data(self):
'''
load & preprocessing dataset from file
'''
users_title = ['UserID', 'Gender', 'Age', 'JobID', 'Zip-code']
users = pd.read_csv(self.UserDataPath, sep='::', header=None, names=users_title, engine='python')
# change the 'gender' expression from dataset
gender_map = {'F':0, 'M':1}
users['Gender'] = users['Gender'].map(gender_map)
# change the 'Age' expression, {1: 0, 18: 1, 25: 2, 35: 3, 45: 4, 50: 5, 56: 6}
age_map = {val:ii for ii,val in enumerate(sorted(set(list(users['Age']))))}
users['Age'] = users['Age'].map(age_map)
return users
處理前的資料:
(env) PS F:\movie_recommender> & f:/movie_recommender/env/Scripts/python.exe f:/movie_recommender/test.py
UserID Gender Age JobID Zip-code
0 1 F 1 10 48067
1 2 M 56 16 70072
2 3 M 25 15 55117
3 4 M 45 7 02460
4 5 M 25 20 55455
... ... ... ... ... ...
6035 6036 F 25 15 32603
6036 6037 F 45 1 76006
6037 6038 F 56 1 14706
6038 6039 F 45 0 01060
6039 6040 M 25 6 11106
[6040 rows x 5 columns]
處理後的資料:
(env) PS F:\movie_recommender> & f:/movie_recommender/env/Scripts/python.exe f:/movie_recommender/test.py
UserID Gender Age JobID Zip-code
0 1 0 0 10 48067
1 2 1 6 16 70072
2 3 1 2 15 55117
3 4 1 4 7 02460
4 5 1 2 20 55455
... ... ... ... ... ...
6035 6036 0 2 15 32603
6036 6037 0 4 1 76006
6037 6038 0 6 1 14706
6038 6039 0 4 0 01060
6039 6040 1 2 6 11106
[6040 rows x 5 columns]
對電影資料進行預處理
- Title欄位:處理方式跟Genres欄位一樣,首先建立文字到數字的字典,然後將Title中的描述轉成數字的列表。另外Title中的年份也需要去掉。
- Genres欄位:是分類欄位,要轉成數字。首先將Genres中的類別轉成字串到數字的字典,然後再將每個電影的Genres欄位轉成數字列表,因為有些電影是多個Genres的組合。
- Genres和Title欄位需要將長度統一,這樣在神經網路中方便處理。空白部分用‘< PAD >’對應的數字填充。
去除title中的年份:
# Remove the 'year' from Title
pattern = re.compile(r'^(.*)\((\d+)\)$')
title_map = {val:pattern.match(val).group(1) for ii,val in enumerate(set(movies['Title']))}
movies['Title'] = movies['Title'].map(title_map)
將電影種類轉化為數字字典:
genres_set = set()
for val in movies['Genres'].str.split('|'):# movies genres are separated via '|'
genres_set.update(val)# store all genres
genres_set.add('<PAD>')
genres2int = {val:ii for ii,val in enumerate(genres_set)}
所有種類:
{'Horror', 'Action', 'Mystery', 'Film-Noir', 'Western', 'Drama', 'Crime', 'Fantasy', 'Musical', "Children's", 'Documentary', '<PAD>', 'Romance', 'Sci-Fi', 'Animation', 'Comedy', 'Adventure', 'Thriller', 'War'}
轉化為數字字典genres2int
:
{'Adventure': 0, 'Documentary': 1, 'Film-Noir': 2, "Children's": 3, 'War': 4, 'Sci-Fi': 5, 'Romance': 6, 'Comedy': 7, '<PAD>': 8, 'Thriller': 9, 'Horror': 10, 'Western': 11, 'Drama': 12, 'Action': 13, 'Crime': 14, 'Animation': 15, 'Fantasy': 16, 'Mystery': 17, 'Musical': 18}
將電影種類轉化為一個固定長度18的lis,不夠的用<PAD>
來補上,部分資料,由於我們生成的數字字典是動態的,再每一次執行的0~17都不一樣,比如這一次執行<PAD>
表示為8,但是下一次可能是10,檢視movies資料集更改後的結果:
MovieID Title Genres
0 1 Toy Story [11, 17, 16, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, ...
1 2 Jumanji [14, 17, 10, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, ...
2 3 Grumpier Old Men [16, 1, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,...
3 4 Waiting to Exhale [16, 18, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6...
4 5 Father of the Bride Part II [16, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,...
... ... ... ...
3878 3948 Meet the Parents [16, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,...
3879 3949 Requiem for a Dream [18, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,...
3880 3950 Tigerland [18, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,...
3881 3951 Two Family House [18, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,...
3882 3952 Contender, The [18, 15, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6...
對於title的處理,因為電影名是幾個單詞幾個單片語成的,我們先用簡單的處理方式處理一下:
將所有標題中出現的單詞,組成過一個set:
, 'Jerry', 'Prince', 'Joe,', 'Richie', 'Mutters', 'Darkness,', 'Vanities', 'Bell,', 'Traffic', 'Jakob', 'Pride', 'Short', 'Romy', 'Got', 'Supper,', 'Wicked', 'Tender', 'del', 'European', 'Deuce', 'Criminels)', 'Crockett,', 'Monte', 'Tigerland', 'belle,', 'Fool', '蒫ole', 'Mall', 'Ozona', 'Purple,', 'Dudley', 'Gigolo', 'Duck', 'Troopers', 'Sleepwalkers', 'Wolves', 'Nuts', '(Zerkalo)', 'Dollhouse', 'Inheritors,', 'Tetsuo', 'Plutonium', 'Good,', 'Cujo',
'(Rekopis', 'Railroad', "It's", 'FairyTale:', 'Paulie', 'Couple,', 'Mighty', 'Just', 'Brothers,', 'Logo', 'Associate,', 'Babyfever', 'Cruise', "Can't",
'Cats', 'Sensibility', 'Half', 'Transit', 'Lives', 'Conformista)', 'Plan', 'Faith', 'Saboteur', 'Bowl,', 'pianista', 'May', 'Turkish', 'Hush', 'Thunderball', 'Alaska', 'Farm', 'Hedd', 'ni', "Fishin'", 'Witness', 'Ruby', 'Scent', '(Se7en)', 'Sunday', 'Passi', 'Swing', 'Assignment,', 'Bits', 'Time', 'Phantoms', 'Verdict,', 'Chapter,', "I'll", 'peor', 'Bloody', 'Mercury', 'Endurance', 'Face', 'Stonewall', 'Stock', 'John', 'Les', 'Place', 'Turtle', 'Prisoner,', 'Ice', 'Love!', 'Choice', 'Fletch', 'Romancing', 'Happy,', 'Gloria', 'Notorious', 'Me,', '鰃a)', 'Lifeboat', 'Peak', 'Ruling', 'Crush,', 'Portrait', 'Extremities', 'SS', 'Rage', 'Sorority', 'Tron', '(Karakter)', 'Ed', 'Africa,', 'Roberts', '(Jing', 'Mifune', 'Jimmy,', 'Consequences,', 'Gambler,'
和轉化文章分類的方法一樣,我們生成一個15長度的list ,不夠的用<PAD>
來補上,部分資料,同樣:由於我們生成的數字字典是動態的,再每一次執行的0~17都不一樣,比如這一次執行<PAD>
表示為8。
程式碼:
# convert movies_title to a list of fixed-length, 15 in length
title_count = 15
title_map = {val:[title2int[row] for row in val.split()] for ii,val in enumerate(set(movies['Title']))}
for key in title_map:
for cnt in range(title_count - len(title_map[key])):
title_map[key].insert(len(title_map[key]) + cnt,title2int['<PAD>'])
movies['Title'] = movies['Title'].map(title_map)
return movies
執行效果:
(env) PS F:\movie_recommender> & f:/movie_recommender/env/Scripts/python.exe f:/movie_recommender/test.py
MovieID Title Genres
0 1 [4581, 1639, 1792, 1792, 1792, 1792, 1792, 179... [17, 18, 5, 13, 13, 13, 13, 13, 13, 13, 13, 13...
1 2 [3920, 1792, 1792, 1792, 1792, 1792, 1792, 179... [16, 18, 8, 13, 13, 13, 13, 13, 13, 13, 13, 13...
2 3 [3661, 537, 1011, 1792, 1792, 1792, 1792, 1792... [5, 11, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13...
3 4 [4026, 2962, 5003, 1792, 1792, 1792, 1792, 179... [5, 1, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,...
4 5 [3996, 2973, 4394, 4317, 3618, 2947, 1792, 179... [5, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13...
... ... ... ...
3878 3948 [1800, 4394, 5012, 1792, 1792, 1792, 1792, 179... [5, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13...
3879 3949 [298, 4143, 3656, 5191, 1792, 1792, 1792, 1792... [1, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13...
3880 3950 [3178, 1792, 1792, 1792, 1792, 1792, 1792, 179... [1, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13...
3881 3951 [1513, 2135, 2105, 1792, 1792, 1792, 1792, 179... [1, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13...
3882 3952 [3063, 2235, 1792, 1792, 1792, 1792, 1792, 179... [1, 2, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,...
[3883 rows x 3 columns]
本作品採用《CC 協議》,轉載必須註明作者和本文連結
文章!!首發於我的部落格Stray_Camel(^U^)ノ~YO。