<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          CCF推薦系統(tǒng)項目代碼解讀!

          共 7646字,需瀏覽 16分鐘

           ·

          2021-12-14 08:00

          ?Datawhale干貨?
          作者:阿水,北京航空航天大學(xué),Datawhale成員

          本文以CCF大數(shù)據(jù)與計算智能大賽(CCF BDCI)圖書推薦系統(tǒng)競賽為實踐背景,使用Paddle構(gòu)建用戶與圖書的打分模型,借助Embedding層來完成具體的匹配過程。后臺回復(fù) 211208?可獲取完整代碼。

          代碼地址
          https://aistudio.baidu.com/aistudio/projectdetail/2556840

          實踐背景

          賽題背景


          賽事地址
          https://www.datafountain.cn/competitions/542

          隨著新型互聯(lián)網(wǎng)的發(fā)展,人類逐漸進入了信息爆炸時代。新型電商網(wǎng)絡(luò)面臨的問題也逐漸轉(zhuǎn)為如何讓用戶從海量的商品中挑選到自己想要的目標(biāo)。推薦系統(tǒng)正是在互聯(lián)網(wǎng)快速發(fā)展之后的產(chǎn)物。

          為幫助電商系統(tǒng)識別用戶需求,為用戶提供其更加感興趣的信息,從而為用戶提供更好的服務(wù),需要依據(jù)真實的圖書閱讀數(shù)據(jù)集,利用機器學(xué)習(xí)的相關(guān)技術(shù),建立一個圖書推薦系統(tǒng)。用于為用戶推薦其可能進行閱讀的數(shù)據(jù),從而在產(chǎn)生商業(yè)價值的同時,提升用戶的閱讀體驗,幫助創(chuàng)建全民讀書的良好社會風(fēng)氣。

          賽題任務(wù)

          依據(jù)真實世界中的用戶-圖書交互記錄,利用機器學(xué)習(xí)相關(guān)技術(shù),建立一個精確穩(wěn)定的圖書推薦系統(tǒng),預(yù)測用戶可能會進行閱讀的書籍。

          賽題數(shù)據(jù)

          數(shù)據(jù)集來自公開數(shù)據(jù)集Goodbooks-10k,包含網(wǎng)站Goodreads中對10,000本書共約6,000,000條評分。為了預(yù)測用戶下一個可能的交互對象,數(shù)據(jù)集已經(jīng)處理為隱式交互數(shù)據(jù)集。該數(shù)據(jù)集廣泛的應(yīng)用于推薦系統(tǒng)中。

          數(shù)據(jù)文件夾包含3個文件,依次為:

          • 訓(xùn)練集: train.csv 訓(xùn)練數(shù)據(jù)集,為用戶-圖書交互記錄
          • 測試集: test.csv 測試數(shù)據(jù)集,只有需要進行預(yù)測用戶ID
          • 提交樣例: submission.csv 僅有兩個字段user_id/item_id

          解題思路

          使用深度學(xué)習(xí)模型構(gòu)建隱式推薦算法模型,并構(gòu)建負(fù)樣本,最終按照模型輸出的評分進行排序,做出最終的推薦。具體可以分為以下幾個步驟:

          • 步驟1:讀取數(shù)據(jù),對用戶和圖書進行編碼;
          • 步驟2:利用訓(xùn)練集構(gòu)建負(fù)樣本;
          • 步驟3:使用Paddle構(gòu)建打分模型;
          • 步驟4:對測試集數(shù)據(jù)進行預(yù)測;

          步驟1:讀取數(shù)據(jù)集

          首先我們使用pandas讀取數(shù)據(jù)集,并對數(shù)據(jù)的字段進行編碼。這里可以手動構(gòu)造編碼過程,也可以使用LabelEncoder來完成。

          這一步驟的操作目的是將對用戶和圖書編碼為連續(xù)的數(shù)值,原始的取值并不是連續(xù)的,這樣可以減少后續(xù)模型所需要的空間。

          步驟2:構(gòu)建負(fù)樣本

          由于原始訓(xùn)練集中都是記錄的是用戶已有的圖書記錄,并不存在負(fù)樣本。而在預(yù)測階段我們需要預(yù)測用戶下一個圖書,此時的預(yù)測空間是用戶對所有圖書的關(guān)系。

          這里構(gòu)建負(fù)樣本的操作非常粗暴,直接是選擇用戶在訓(xùn)練集中沒有圖書。這里可以先使用協(xié)同過濾的思路來構(gòu)建負(fù)樣本,即將負(fù)樣本是相似用戶都沒有記錄的圖書。

          步驟3:Paddle搭建打分模型

          這里使用Paddle構(gòu)建用戶與圖書的打分模型,借助Embedding層來完成具體的匹配過程。這里用最簡單的dot來完成匹配,沒有構(gòu)建復(fù)雜的模型。

          步驟4:對測試集進行預(yù)測

          首先將測試集數(shù)據(jù)轉(zhuǎn)為模型需要的格式,然后一行代碼完成預(yù)測即可,然后轉(zhuǎn)換為提交格式。

          改進思路

          由于現(xiàn)有的代碼寫的比較基礎(chǔ),所以有很多改進的步驟:

          • 對模型精度進行改進,可以考慮構(gòu)建更加復(fù)雜的模型,并對訓(xùn)練集負(fù)樣本構(gòu)造過程進行改進。

          • 對模型使用內(nèi)存,可以考慮使用Numpy代替Pandas的操作。

          代碼實踐

          讀取數(shù)據(jù)集

          #?查看當(dāng)前掛載的數(shù)據(jù)集目錄,?該目錄下的變更重啟環(huán)境后會自動還原
          #?View?dataset?directory.?
          #?This?directory?will?be?recovered?automatically?after?resetting?environment.?

          !unzip?/home/aistudio/data/data114712/train_dataset.zip
          Archive:??/home/aistudio/data/data114712/train_dataset.zip
          ??inflating:?train_dataset.csv???????

          !cp?/home/aistudio/data/data114712/test_dataset.csv?./

          !head?train_dataset.csv
          user_id,item_id

          import?pandas?as?pd
          import?numpy?as?np
          import?paddle
          import?paddle.nn?as?nn
          from?paddle.io?import?Dataset

          df?=?pd.read_csv('train_dataset.csv')
          user_ids?=?df["user_id"].unique().tolist()

          user2user_encoded?=?{x:?i?for?i,?x?in?enumerate(user_ids)}
          userencoded2user?=?{i:?x?for?i,?x?in?enumerate(user_ids)}

          book_ids?=?df["item_id"].unique().tolist()
          book2book_encoded?=?{x:?i?for?i,?x?in?enumerate(book_ids)}
          book_encoded2book?=?{i:?x?for?i,?x?in?enumerate(book_ids)}

          df["user"]?=?df["user_id"].map(user2user_encoded)
          df["movie"]?=?df["item_id"].map(book2book_encoded)

          num_users?=?len(user2user_encoded)
          num_books?=?len(book_encoded2book)

          user_book_dict?=?df.iloc[:].groupby(['user'])['movie'].apply(list)

          user_book_dict
          user

          構(gòu)造負(fù)樣本

          neg_df?=?[]
          book_set?=?set(list(book_encoded2book.keys()))
          for?user_idx?in?user_book_dict.index:
          ????book_idx?=?book_set?-?set(list(user_book_dict.loc[user_idx]))
          ????book_idx?=?list(book_idx)
          ????neg_book_idx?=?np.random.choice(book_idx,?100)
          ????for?x?in?neg_book_idx:
          ????????neg_df.append([user_idx,?x])

          neg_df?=?pd.DataFrame(neg_df,?columns=['user',?'movie'])
          neg_df['label']?=?0

          df['label']?=?1
          train_df?=?pd.concat([df[['user',?'movie',?'label']],?
          ??????????????????????neg_df[['user',?'movie',?'label']]],?axis=0)

          train_df?=?train_df.sample(frac=1)

          del?df;

          自定義數(shù)據(jù)集

          #?自定義數(shù)據(jù)集

          #?映射式(map-style)數(shù)據(jù)集需要繼承paddle.io.Dataset
          class?SelfDefinedDataset(Dataset):
          ????def?__init__(self,?data_x,?data_y,?mode?=?'train'):
          ????????super(SelfDefinedDataset,?self).__init__()
          ????????self.data_x?=?data_x
          ????????self.data_y?=?data_y
          ????????self.mode?=?mode

          ????def?__getitem__(self,?idx):
          ????????if?self.mode?==?'predict':
          ????????????return?self.data_x[idx]
          ????????else:
          ????????????return?self.data_x[idx],?self.data_y[idx]
          ????
          ????def?__len__(self):
          ????????return?len(self.data_x)


          from?sklearn.model_selection?import?train_test_split
          x_train,?x_val,?y_train,?y_val?=?train_test_split(train_df[['user',?'movie']].values,?
          ????????????????????????????????????????train_df['label'].values.astype(np.float32).reshape(-1,?1))

          traindataset?=?SelfDefinedDataset(x_train,?y_train)
          for?data,?label?in?traindataset:
          ????print(data.shape,?label.shape)
          ????print(data,?label)
          ????break

          train_loader?=?paddle.io.DataLoader(traindataset,?batch_size?=?1280*4,?shuffle?=?True)
          for?batch_id,?data?in?enumerate(train_loader):
          ????x_data?=?data[0]
          ????y_data?=?data[1]
          ????
          ????print(x_data.shape)
          ??print(y_data.shape)
          ??break
          ??
          val_dataset?=?SelfDefinedDataset(x_val,?y_val)
          val_loader?=?paddle.io.DataLoader(val_dataset,?batch_size?=?1280*4,?shuffle?=?True)????????
          for?batch_id,?data?in?enumerate(val_loader):
          ????x_data?=?data[0]
          ????y_data?=?data[1]
          ????
          ????print(x_data.shape)
          ??print(y_data.shape)
          ??break

          定義模型

          EMBEDDING_SIZE?=?32

          class?RecommenderNet(nn.Layer):
          ????def?__init__(self,?num_users,?num_movies,?embedding_size):
          ????????super(RecommenderNet,?self).__init__()
          ????????self.num_users?=?num_users
          ????????self.num_movies?=?num_movies
          ????????self.embedding_size?=?embedding_size
          ????????weight_attr_user?=?paddle.ParamAttr(
          ????????????regularizer?=?paddle.regularizer.L2Decay(1e-6),
          ????????????initializer?=?nn.initializer.KaimingNormal()
          ????????????)
          ????????self.user_embedding?=?nn.Embedding(
          ????????????num_users,
          ????????????embedding_size,
          ????????????weight_attr=weight_attr_user
          ????????)
          ????????self.user_bias?=?nn.Embedding(num_users,?1)
          ????????
          ????????weight_attr_movie?=?paddle.ParamAttr(
          ????????regularizer?=?paddle.regularizer.L2Decay(1e-6),
          ????????initializer?=?nn.initializer.KaimingNormal()
          ????????)
          ????self.movie_embedding?=?nn.Embedding(
          ????????num_movies,
          ????????embedding_size,
          ????????weight_attr=weight_attr_movie
          ????)
          ????self.movie_bias?=?nn.Embedding(num_movies,?1)
          ????
          ??def?forward(self,?inputs):
          ??????user_vector?=?self.user_embedding(inputs[:,?0])
          ??????user_bias?=?self.user_bias(inputs[:,?0])
          ??????movie_vector?=?self.movie_embedding(inputs[:,?1])
          ??????movie_bias?=?self.movie_bias(inputs[:,?1])
          ??????dot_user_movie?=?paddle.dot(user_vector,?movie_vector)
          ??????x?=?dot_user_movie?+?user_bias?+?movie_bias
          ??????x?=?nn.functional.sigmoid(x)
          ??????return?x

          model?=?RecommenderNet(num_users,?num_books,?EMBEDDING_SIZE)

          model?=?paddle.Model(model)
          optimizer?=?paddle.optimizer.Adam(parameters=model.parameters(),?learning_rate=0.003)
          loss?=?nn.BCELoss()
          metric?=?paddle.metric.Precision()

          ##?設(shè)置visualdl路徑
          log_dir?=?'./visualdl'
          callback?=?paddle.callbacks.VisualDL(log_dir=log_dir)

          model.prepare(optimizer,?loss,?metric)
          model.fit(train_loader,?val_loader,?epochs=5,?save_dir='./checkpoints',?verbose=1,?callbacks=callback)

          預(yù)測測試集

          test_df?=?[]
          with?open('sub.csv',?'w')?as?up:
          ????up.write('user_id,item_id\n')
          ????
          book_set?=?set(list(book_encoded2book.keys()))
          for?idx?in?range(int(len(user_book_dict)/1000)?+1):
          ????test_user_idx?=?[]
          ????test_book_idx?=?[]
          ????for?user_idx?in?user_book_dict.index[idx*1000:(idx+1)*1000]:
          ????????book_idx?=?book_set?-?set(list(user_book_dict.loc[user_idx]))
          ????????book_idx?=?list(book_idx)
          ????????test_user_idx?+=?[user_idx]?*?len(book_idx)
          ????????test_book_idx?+=??book_idx

          ????test_data?=?np.array([test_user_idx,?test_book_idx]).T
          ????test_dataset?=?SelfDefinedDataset(test_data,?data_y=None,?mode='predict')
          ????test_loader?=?paddle.io.DataLoader(test_dataset,?batch_size=1280,?shuffle?=?False)????????

          ????test_predict?=?model.predict(test_loader,?batch_size=1024)
          ????test_predict?=?np.concatenate(test_predict[0],?0)

          ????test_data?=?pd.DataFrame(test_data,?columns=['user',?'book'])
          ????test_data['label']?=?test_predict
          ????for?gp?in?test_data.groupby(['user']):
          ????????with?open('sub.csv',?'a')?as?up:
          ????????????u?=?gp[0]
          ????????????b?=?gp[1]['book'].iloc[gp[1]['label'].argmax()]
          ????????????up.write(f'{userencoded2user[u]},?{book_encoded2book[b]}\n')

          ????del?test_data,?test_dataset,?test_loader
          ????????




          整理不易,三連
          瀏覽 37
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  伊人AV综合 | 国产极品 国产极品 | 啪啪啪免费网站视频 | 天堂网www.资源在线 | 深爱激情五月天 |