程世東老師TensorFlow實戰——個性化推薦,程式碼學習筆記之資料匯入&資料預處理
#執行下面程式碼把資料下載下來 import pandas as pd from sklearn.model_selection import train_test_split #資料集劃分訓練集和測試集 import numpy as np from collections import Counter #counter用於統計字元出現的次數 import tensorflow as tf import os #os 模組提供了非常豐富的方法用來處理檔案和目錄 import pickle #提供儲存資料在本地的方法 import re #正則表示式 from tensorflow.python.ops import math_ops from urllib.request import urlretrieve #將URL表示的網路物件複製到本地檔案 from os.path import isfile, isdir #判斷是否存在檔案file,資料夾dir from tqdm import tqdm #Tqdm 是一個快速,可擴充套件的Python進度條,可以在 Python 長迴圈中新增一個進度提示資訊,使用者只需要封裝任意的迭代器 tqdm(iterator) import zipfile #用來做zip格式編碼的壓縮和解壓縮的 import hashlib #用來進行hash 或者md5 加密 def _unzip(save_path, _, database_name, data_path): """ Unzip wrapper with the same interface as _ungzip使用與_ungzip相同的介面解壓縮包裝器 :param save_path: gzip檔案的路徑 :param database_name:資料庫的名稱 :param data_path: 提取路徑 :param _: HACK - Used to have to same interface as _ungzip 用於與_ungzip具有相同的介面??解壓後的檔案路徑 """ print('Extracting {}...'.format(database_name))#.format通過 {} 來代替字串database_name with zipfile.ZipFile(save_path) as zf: #ZipFile是zipfile包中的一個類,用來建立和讀取zip檔案 zf.extractall(data_path) #類函式zipfile.extractall([path[, member[, password]]]) #path解壓縮目錄,沒什麼可說的 # member需要解壓縮的檔名列表 # password當zip檔案有密碼時需要該選項 def download_extract(database_name, data_path): """ 下載並提取資料庫 :param database_name: Database name data_path 這裡為./表示當前目錄 save_path 下載後資料的儲存路徑即壓縮檔案的路徑 extract_path 解壓後的檔案路徑 """ DATASET_ML1M = 'ml-1m' if database_name == DATASET_ML1M: url = 'http://files.grouplens.org/datasets/movielens/ml-1m.zip' hash_code = 'c4d9eecfca2ab87c1945afe126590906' extract_path = os.path.join(data_path, 'ml-1m')#os.path.join將多個路徑組合後返回,提取資料的路徑 save_path = os.path.join(data_path, 'ml-1m.zip')#要儲存的路徑 extract_fn = _unzip if os.path.exists(extract_path): #指定路徑(檔案或者目錄)是否存在 print('Found {} Data'.format(database_name)) return if not os.path.exists(data_path): #指定路徑(檔案或者目錄)不存在,則遞迴建立目錄data_path os.makedirs(data_path) if not os.path.exists(save_path): #指定路徑(檔案或者目錄)不存在,則遞迴建立目錄save_path with DLProgress(unit='B', unit_scale=True, miniters=1, desc='Downloading {}'.format(database_name)) as pbar:#呼叫類,進度條顯示相關,tqdm相關引數設定 urlretrieve(url, save_path, pbar.hook) #urlretrieve()方法直接將遠端資料下載到本地 rlretrieve(url, filename=None, reporthook=None, data=None) #filename指定了儲存本地路徑 #reporthook是回撥函式,當連線上伺服器、以及相應的資料塊傳輸完畢時會觸發該回調,可利用回撥函式顯示當前下載進度。 assert hashlib.md5(open(save_path, 'rb').read()).hexdigest() == hash_code, \ '{} file is corrupted. Remove the file and try again.'.format(save_path) #assert expression [, arguments]表示斷言測試,如expression異常,則輸出後面字串資訊 #能指出資料是否被篡改過,就是因為摘要函式是一個單向函式,計算f(data)很容易,但通過digest反推data卻非常困難。而且,對原始資料做一個bit的修改,都會導致計算出的摘要完全不同。 #摘要演算法應用:使用者儲存使用者名稱密碼,但在資料庫不能以明文儲存,而是用md5,當一個使用者輸入密碼時,進行md5匹配,如果相同則可以登入 #hashlib提供了常見的摘要演算法,如MD5,SHA1等等。摘要演算法又稱雜湊演算法、雜湊演算法。它通過一個函式,把任意長度的資料轉換為一個長度固定的資料串(通常用16進位制的字串表示)。 #hexdigest為md5後的結果 os.makedirs(extract_path) try: extract_fn(save_path, extract_path, database_name, data_path)#解壓 except Exception as err: shutil.rmtree(extract_path) # Remove extraction folder if there is an error表示遞迴刪除資料夾下的所有子資料夾和子檔案 raise err#丟擲異常 print('Done.') # Remove compressed data # os.remove(save_path) class DLProgress(tqdm): """ Handle Progress Bar while Downloading下載時處理進度條 """ last_block = 0 def hook(self, block_num=1, block_size=1, total_size=None): """ 該函式在建立網路連線時呼叫一次,之後在每個塊讀取後呼叫一次. :param block_num: 到目前為止轉移的塊數 :param block_size: 塊大小(位元組) :param total_size: 檔案的總大小。 對於較舊的FTP伺服器,這可能為-1,該伺服器不響應檢索請求而返回檔案大小。 """ self.total = total_size self.update((block_num - self.last_block) * block_size) self.last_block = block_num data_dir = './' download_extract('ml-1m', data_dir) #------------------------------------------------------------------------------ #實現資料預處理 def load_data(): """ Load Dataset from File """ #讀取User資料------------------------------------------------------------- users_title = ['UserID', 'Gender', 'Age', 'JobID', 'Zip-code'] users = pd.read_table('./ml-1m/users.dat', sep='::', header=None, names=users_title, engine = 'python') #分隔符引數:sep #是否讀取文字資料的header,headers = None表示使用預設分配的列名,一般用在讀取沒有header的資料檔案 #為文字的資料加上自定義列名: names #pandas.read_csv()從檔案,URL,檔案型物件中載入帶分隔符的資料。預設分隔符為',' #pandas.read_table()從檔案,URL,檔案型物件中載入帶分隔符的資料。預設分隔符為'\t' users = users.filter(regex='UserID|Gender|Age|JobID') #DataFrame.filter(items=None, like=None, regex=None, axis=None) #這裡使用正則式進行過濾 users_orig = users.values #dataframe.values以陣列的形式返回DataFrame的元素 #改變User資料中性別和年齡 gender_map = {'F':0, 'M':1} users['Gender'] = users['Gender'].map(gender_map) #map()函式可以用於Series物件或DataFrame物件的一列,接收函式或字典物件作為引數,返回經過函式或字典對映處理後的值。 age_map = {val:ii for ii,val in enumerate(set(users['Age']))} #enumerate() 函式用於將一個可遍歷的資料物件(如列表、元組或字串)組合為一個索引序列 #同時列出資料和資料下標,一般用在 for 迴圈當中 #set() 函式建立一個無序不重複元素集 users['Age'] = users['Age'].map(age_map) #map接收的引數是函式 #讀取Movie資料集--------------------------------------------------------- movies_title = ['MovieID', 'Title', 'Genres'] movies = pd.read_table('./ml-1m/movies.dat', sep='::', header=None, names=movies_title, engine = 'python') movies_orig = movies.values #將Title中的年份去掉 pattern = re.compile(r'^(.*)\((\d+)\)$') #re.compile(strPattern[, flag]):把正則表示式的模式和標識轉化成正則表示式物件。供match()和search()這兩個函式使用 #第二個引數flag是匹配模式,取值可以使用按位或運算子'|'表示同時生效 #r表示後面是一個正則表示式'' #^匹配開頭,$匹配結尾,(.*)中的()表示匹配其中的任意正則表示式,.匹配任何字元,*代表可以重複0次或多次 #\(和\):表示對括號的轉義,匹配文字中真正的括號 #(\d+)表示匹配()內的任意字元,\d表示任何數字,+代表數字重複一次或者多次 title_map = {val:pattern.match(val).group(1) for ii,val in enumerate(set(movies['Title']))} #這裡的ii是索引值,val是真正的列表中Title元素 #pattern.match(val)使用Pattern匹配文字val,獲得匹配結果,無法匹配時將返回None #group獲得一個或多個分組截獲的字串;指定多個引數時將以元組形式返回,分組是按照()匹配順序進行 #這裡group(1)相當於只返回第一組,分組標號從1開始。不填則為返回全部結果 #這裡即完成了將電影名稱的時間去掉 movies['Title'] = movies['Title'].map(title_map)#title列的電影名轉化為去掉名稱後的電影名 #電影Title轉數字字典 title_set = set() #set() 函式建立一個無序不重複元素集,返回一個可迭代物件 for val in movies['Title'].str.split():#對於電影名稱按空格分,val為整個電影列表中全部單詞 #注意string.split() 不帶引數時,和 string.split(' ') 是有很大區別的 #不帶引數的不會截取出空格,而帶引數的只按一個空格去切分,多出來的空格會被截取出來 #參見https://code.ziqiangxuetang.com/python/att-string-split.html title_set.update(val)#新增新元素到集合當中,即完成出現電影中的新單詞時,存下來 title_set.add('<PAD>')#這裡不是numpy.pad函式,只是一個填充表示,也為<PAD>進行編碼 title2int = {val:ii for ii, val in enumerate(title_set)}#為全部單詞進行像字典一樣進行標註'描述電影的word:數字'格式,即數字字典 #將電影Title轉成等長數字列表,長度是15 title_count = 15 title_map = {val:[title2int[row] for row in val.split()] for ii,val in enumerate(set(movies['Title']))} #for ii,val in enumerate(set(movies['Title']))得到ii索引值和其對應的不重複的一個電影字串val(去掉月份的) #val.split()得到全部被空格分開的電影名稱字串列表,row遍歷電影集中一個電影的全部單詞 #title_map得到的是字典,格式為'一個電影字串:[描述這個電影的全部單詞構成的一個對應的數值列表]' 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>'])#insert(index, object) 在指定位置index前插入元素object #index ,object 電影key長度少於15就加填充符 movies['Title'] = movies['Title'].map(title_map)#title欄位的去掉名稱後的電影名轉化為對應的數字列表 #如電影集中的一行資料如下movieid,title,genre # array([1, # list([3001, 5100, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275, 275]), # list([3, 6, 2, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17])], dtype=object) #電影型別轉數字字典 genres_set = set() for val in movies['Genres'].str.split('|'):#對於一個電影的題材進行字串轉化,並用|分割遍歷 genres_set.update(val) #set.update()方法用於修改當前集合,可以新增新的元素或集合到當前集合中,如果新增的元素在集合中已存在,則該元素只會出現一次,重複的會忽略。 #將描述不同題材的電影存入set genres_set.add('<PAD>') #集合add方法:是把要傳入的元素做為一個整個新增到集合中,為<PAD>進行編碼 genres2int = {val:ii for ii, val in enumerate(genres_set)}#將型別轉化為'字串:數字'格式,即數字字典,同上面電影名稱,一個word對應一個數字 #而一個電影由多個word構成 #將電影型別轉成等長數字列表,長度是18 genres_map = {val:[genres2int[row] for row in val.split('|')] for ii,val in enumerate(set(movies['Genres']))} for key in genres_map: for cnt in range(max(genres2int.values()) - len(genres_map[key])): genres_map[key].insert(len(genres_map[key]) + cnt,genres2int['<PAD>']) movies['Genres'] = movies['Genres'].map(genres_map) #讀取評分資料集-------------------------------------------------------- ratings_title = ['UserID','MovieID', 'ratings', 'timestamps'] ratings = pd.read_table('./ml-1m/ratings.dat', sep='::', header=None, names=ratings_title, engine = 'python') ratings = ratings.filter(regex='UserID|MovieID|ratings') #合併三個表 data = pd.merge(pd.merge(ratings, users), movies)#通過一個或多個鍵將兩個資料集的行連線起來,類似於 SQL 中的 JOIN #合併左dataframe和右datafram,預設為取交集,取交集作為索引鍵 #將資料分成X和y兩張表 target_fields = ['ratings'] features_pd, targets_pd = data.drop(target_fields, axis=1), data[target_fields] #features_pd只剩userid和rating作為x表;targets_pd只有rating作為y #刪除表中的某一行或者某一列使用drop,不改變原有的df中的資料,而是返回另一個dataframe來存放刪除後的資料。 features = features_pd.values targets_values = targets_pd.values return title_count, title_set, genres2int, features, targets_values, ratings, users, movies, data, movies_orig, users_orig #title_count電影名長度15 #title_set {索引:去掉年份且不重複的電影名} #genres2int {題材字串列表:數字} #features 使用者ID+評分,輸入x #targets_values 評分,學習目標y #返回處理後的ratings,users,movies表,pandas物件 #返回三表的合併表data #moives表中的原始資料值:movies_orig #users表中的原始資料值:users_orig #--------------------------------------------------------------------------- #載入資料並儲存到本地 title_count, title_set, genres2int, features, targets_values, ratings, users, movies, data, movies_orig, users_orig = load_data() pickle.dump((title_count, title_set, genres2int, features, targets_values, ratings, users, movies, data, movies_orig, users_orig), open('preprocess.p', 'wb')) #pickle.dump(obj, file[, protocol])序列化物件,並將結果資料流寫入到檔案物件中 #引數protocol是序列化模式,預設值為0,表示以文字的形式序列化 #protocol的值還可以是1或2,表示以二進位制的形式序列化。 #從本地讀取資料 title_count, title_set, genres2int, features, targets_values, ratings, users, movies, data, movies_orig, users_orig = pickle.load(open('preprocess.p', mode='rb'))
相關推薦
程世東老師TensorFlow實戰——個性化推薦,程式碼學習筆記之資料匯入&資料預處理(上)
程式碼來自於知乎:https://zhuanlan.zhihu.com/p/32078473 /程式碼地址https://github.com/chengstone/movie_recommender/blob/master/movie_recommender.ipynb 下一篇有一些資料的
程世東老師TensorFlow實戰——個性化推薦,程式碼學習筆記之資料匯入&資料預處理(下)
這篇主要是進行程式碼中的一些數值視覺化,幫助理解 程式碼來自於知乎:https://zhuanlan.zhihu.com/p/32078473 /程式碼地址https://github.com/chengstone/movie_recommender/blob/master/movie_re
程世東老師TensorFlow實戰——個性化推薦,程式碼學習筆記之③推薦過程
個性化推薦第三部分:推薦過程(完結撒花) 程式碼來自於知乎:https://zhuanlan.zhihu.com/p/32078473 /程式碼地址https://github.com/chengstone/movie_recommender/blob/master/movie_recomm
程世東老師TensorFlow實戰——個性化推薦,程式碼學習筆記之②模型訓練與測試
個性化推薦第二部分:模型訓練 程式碼來自於知乎:https://zhuanlan.zhihu.com/p/32078473 /程式碼地址https://github.com/chengstone/movie_recommender/blob/master/movie_recommender.
程世東老師TensorFlow實戰——個性化推薦,程式碼學習筆記之資料匯入&資料預處理
#執行下面程式碼把資料下載下來 import pandas as pd from sklearn.model_selection import train_test_split #資料集劃分訓練集和測試集 import numpy as np from coll
學習筆記之T-SQL插入數據INSERT語法和數據庫編程實戰技巧[圖]
INSERT 數據庫 IT 編程 學習 一直以來就有寫博客的習慣,記錄一下學習心得、生活點滴等等,感覺也蠻好的,去年開始萌生了建立一個讀書和文學博客的想法,於是就開始實施了,中途也遇到不少難題,不過還好,都逐漸解決了,雖然我在技術方面有欠缺,但好在有同學們幫忙。 今天想和大家分享的學習筆記
千人千面、個性化推薦,解讀數據賦能商家背後的AI技術
div 並且 聊天 接收 線上 體驗 超越 金礦 docke 12月6~7日,由阿裏巴巴集團、阿裏巴巴技術發展部、阿裏雲雲棲社區聯合主辦,以“2016 雙 11 技術創新”為主題的阿裏巴巴技術論壇,來自商家事業部的技術總監魏虎給大家分享了數據賦能商家背後的AI技術。首先對大
乾貨 | 個性化推薦系統五大研究熱點之深度學習(一)
【編者按】在這個科技高速發展、資訊爆炸的時代,毫不誇張地說,推薦系統已經完全融入了我們的生活。我們去哪一家餐館、買哪一件衣服、瀏覽哪一類資訊、觀看哪一種視訊,很大程度上都取決於背後的推薦系統。 在本文中,微軟亞洲研究院社會計算組的研究員們從深度學習、知識圖譜、強化學習、使用者畫像、可解釋性推薦等五個方面,展望
乾貨|個性化推薦系統五大研究熱點之可解釋推薦(五)
【編者按】微軟亞洲研究院社會計算組的研究員們從深度學習、知識圖譜、強化學習、使用者畫像、可解釋性推薦等五個方面,展望了未來推薦系統發展的方向。 在前幾篇文章中,我們分別介紹了深度學習、知識圖譜、強化學習、使用者畫像在推薦系統中的應用以及未來可能的研究方向。在今天的最後一篇文章中,我們將介紹推薦系
深度學習與TensorFlow實戰(一)深度學習基本概述
傳統的機器學習演算法例如SVM、Boosting、最大熵、LR都屬於淺層的機器學習模型,這些模型只有一層隱藏節點,或者沒有隱藏節點(LR),其侷限在於有限樣本和計算單單元對複雜函式的表示能力有限,泛化能力的侷限性也較大。深度學習可以通過學習深層非線性網路結構,實
推薦算法學習筆記
sent ges 智慧 mms 容易 轉換 ext 集合 view 推薦算法舉個簡單的例子,比如有個用戶進來看了一堆內容,我們把他看的所有的歷史行為,嵌入到推薦引擎當中去。這個推薦引擎就會生成個性化的頻道,下次這個用戶再登錄,或者都不用下一次,過幾分鐘之後,他看到的內容就會
[C#學習筆記之異步編程模式2]BeginInvoke和EndInvoke方法 (轉載)
cti otf 函數返回 編程模式 catch 數值 gin 單線程 blog 為什麽要進行異步回調?眾所周知,普通方法運行,是單線程的,如果中途有大型操作(如:讀取大文件,大批量操作數據庫,網絡傳輸等),都會導致方法阻塞,表現在界面上就是,程序卡或者死掉,界面元素不動了,
《SAS編程與數據挖掘商業案例》學習筆記之十二
style rename today 降序排序 cat list append span nod 本次重點在:sas數據集管理 主要包含:包含數據集縱向拼接、轉置、排序、比較、復制、重命名、刪除等 1.append語句 註:base數據集
JavaSE 學習筆記之網絡編程(二十三)
-c 可能 nbsp blog col accept 接收 存儲 pri 端口: 物理端口: 邏輯端口:用於標識進程的邏輯地址,不同進程的標識;有效端口:0~65535,其中0~1024系統使用或保留端口。 java 中ip對象:InetAddress. import
《SAS編程與數據挖掘商業案例》學習筆記之十一
ror otto -c ace mov 得到 replace 讀書筆記 集中 繼續讀書筆記,本文重點側重sas觀測值的操作方面, 主要包含:輸出觀測值、更新觀測值、刪除觀測值、停止輸出觀測值等
Java 學習筆記之 Sleep停止線程
run rgs ges xtend over exce http tac p s Sleep停止線程: 在Sleep狀態下被interrupt,interrupted 狀態會被擦除,返回false。 線程在Sleep狀態下被interrupt: public clas
Oracle學習筆記之PL/SQL編程
.cn 數據操作 dmi int 直接 字節 sql編程 gin number SQL(Structure Query Language)的含義是結構化查詢語句,最早由Boyce和Chambedin在1974年提出,稱為SEQUEL語言。1976年
Java 學習筆記之 線程安全
div ora mage 線程安全 cnblogs cor exception rup ron 線程安全: 線程安全的方法一定是排隊運行的。 public class SyncObject { synchronized public void met
java學習筆記之初識多線程
技術 運行 必須 dex ima this 認識 主線程 inf 初識多線程 一.進程的認識: 1.進程的理解: 進程可以理解成正在執行的任務,就是正在運行的程序,進程又分為兩種,一種是前臺進程,就是我們很直觀看見的,另一種是後臺進程,就是操作系統啟動就有的(系統級
java學習筆記之網絡編程
col client 應用場景 err pri 多圖片 data oca 網絡 網絡編程 一.網絡通信協議 1.網絡協議 不同的操作系統,不同的硬件設備上都能夠聯網,是因為互聯網設計規定了一套標準,這套標準就被稱為網絡協議,網絡協議規定了網絡傳輸的格式,速率和方