数据预处理 demo

对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
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!