国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

深度學習 - 40. N-Gram 采樣與 Session 數(shù)據(jù)獲取 For EGES

這篇具有很好參考價值的文章主要介紹了深度學習 - 40. N-Gram 采樣與 Session 數(shù)據(jù)獲取 For EGES。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

目錄

一.引言

二.訂單數(shù)據(jù)預(yù)處理

1.數(shù)據(jù)樣例

2.訂單數(shù)據(jù)處理

3.用戶 Session 構(gòu)建

三.構(gòu)造 sku_id 游走序列

1.獲取完整 Session List

2.統(tǒng)計 sku_id 轉(zhuǎn)移詞頻

3.構(gòu)建 sku_id 圖

4.游走構(gòu)造 sku 序列

四.商品側(cè)信息預(yù)處理

1.讀取商品信息

2.Left Join 匹配側(cè)信息

3.Id2Index 構(gòu)建

五.基于 Ngram 與 Negative Sample 的樣本生成

1.自定義 Ngram 樣本生成

2.keras.preprocessing.sequence.skipgrams 樣本生成

3.tf.random.log_uniform_candidate_sampler 采樣負樣本

六.總結(jié)


一.引言

上一篇文章?EGES 與推薦系統(tǒng)用戶冷啟動?一文中我們針對 EGES 論文中提到的一些關(guān)鍵要素進行了分析,在 Word2vec 的基礎(chǔ)上,其創(chuàng)新點主要分為兩個部分:

? 通過 Session 構(gòu)建用戶序列代替

? 在原有數(shù)據(jù)中引入 Side Info 側(cè)信息提高 Emb?表達能力

深度學習 - 40. N-Gram 采樣與 Session 數(shù)據(jù)獲取 For EGES

本文將主要基于訂單數(shù)據(jù)介紹 EGES 模型的數(shù)據(jù)準備工作,后續(xù)會通過 Keras 基于該數(shù)據(jù)進行后續(xù)的 EGES 模型構(gòu)建。

二.訂單數(shù)據(jù)預(yù)處理

1.數(shù)據(jù)樣例

數(shù)據(jù)處理前,首先看下數(shù)據(jù)的原始樣式:

- 訂單數(shù)據(jù)

user_id,sku_id,action_time,module_id,type
937922,357022,2018-02-04 08:28:15,8107857,1
937922,73,2018-02-04 08:27:07,8107857,1
937922,29583,2018-02-04 08:26:31,8107857,1
937922,108763,2018-02-04 08:26:10,8107857,1
1369473,331139,2018-02-03 21:55:49,3712240,1
1330642,69016,2018-02-01 12:47:23,1844129,1
1330642,211690,2018-02-01 12:48:50,1844129,1
1330642,322692,2018-02-01 12:48:15,1844129,1
1330642,19643,2018-02-01 12:47:55,1844129,1

這里原始數(shù)據(jù)包含 user_id、sku_id、action_time、module_id 以及 type,后續(xù)我們主要關(guān)注

??sku_id

商品id,可以理解為后續(xù) word2vec 里的 word,因為我們要根據(jù) sku_id 構(gòu)建用戶行為序列

??action_time

訂單時間,主要用于判定不同 Session 之間的間隔,從而劃分不同的 Session 與 Seq

??type

行為類型,例如點擊、購買等等,該值后續(xù)應(yīng)用于 Session 的判斷,當 type 表示付款下單時,我們可以認為是一次購買行為的結(jié)束,即 Session 的分割點

- 商品信息

sku_id,brand,shop_id,cate,market_time
226519,6302,2399,79,2015-07-02 11:19:04.0
63114,9167,4216,79,2016-07-08 14:29:12.0
372345,2748,7125,79,2016-04-07 16:21:40.0
366931,2698,10252,79,2016-09-11 15:00:22.0
174979,8368,871,79,2017-12-06 17:56:17.0
295436,6302,2399,79,2015-07-02 11:19:04.0
282251,6302,2399,79,2015-07-02 11:19:04.0
146764,6302,2399,79,2015-07-02 11:19:04.0
130851,6302,2399,79,2015-07-02 11:19:04.0

這里包含 sku_id、brand、shop_id、cate 與 market_time,除去 market_time,brand-品牌、shop_id-店鋪以及 cate-商品標簽 都可以視作是商品的 SideInfo 即 EGES 要引入的商品側(cè)信息,所以后續(xù)除了通過訂單數(shù)據(jù)獲取用戶的游走序列外,我們還需要為目標詞匹配其 Side Info。

2.訂單數(shù)據(jù)處理

    # dropna() 函數(shù)的作用是去除讀入的數(shù)據(jù)中(DataFrame)含有NaN的行,這里 axis 默認為0即刪除含 Nan 的行
    # parse_dates 解析時間列 處理后包含 user_id sku_id action_time type 信息
    action_data = pd.read_csv(args.data_path + 'action_head.csv', parse_dates=['action_time']) \
        .drop('module_id', axis=1).dropna()

    # 獲取全部 sku_id 銷售品編碼,此處共 34048 個 Sku
    all_skus = action_data['sku_id'].unique()
    sku_num = len(list(all_skus))
    all_skus = pd.DataFrame({'sku_id': list(all_skus)})
    # 將 sku 編碼到 0-34047 的 id
    sku_lbe = LabelEncoder()
    all_skus['sku_id'] = sku_lbe.fit_transform(all_skus['sku_id'])
    action_data['sku_id'] = sku_lbe.transform(action_data['sku_id'])
    print('make session list\n')

訂單數(shù)據(jù)邏輯比較清晰:

A.讀取 csv 文件,解析訂單 action_time,去除無關(guān)列 module_id 并過濾掉包含 Nan 的異常數(shù)據(jù)

B.對 sku_id 去重獲取當前訂單中所有 sku_id 的去重集合

C.通過 LabelEncoder 對 sku_id 編碼并更新到對應(yīng)的 DataFrame 列中

經(jīng)過這一步數(shù)據(jù)處理,原始訂單數(shù)據(jù)存儲到 Python 的 DataFrame 中,其樣式為:

深度學習 - 40. N-Gram 采樣與 Session 數(shù)據(jù)獲取 For EGES

Tips:

論文中還給出更為細節(jié)的異常數(shù)據(jù)過濾方法:

??去除非置信正樣本

點擊后的停留時間小于1秒,則該點擊可能是無意的,需要刪除,這里其實針對的是用戶誤點擊或者誤觸造成的不置信的正樣本。

??過度活躍樣本

淘寶有一些 "過度活躍" 的用戶,他們實際上是垃圾用戶。根據(jù)我們在淘寶的長期觀察,如果一個用戶在不到 3 個月的時間里購買了1000 件商品或者總點擊量超過 3500 次,那么這個用戶很有可能是一個垃圾用戶。

??高頻更新樣本

淘寶上的零售商不斷更新商品的詳細信息。在極端的情況下,一件商品在經(jīng)過長時間的更新后,在淘寶上的同一個標識符可能會變成完全不同的商品。因此,我們刪除了同一個標識下不斷更新的 Item,以免其語義變化對模型推理引入噪聲。

上述三個條件需要端上記錄更多點擊時長或者商品的更新歷史等,大家在實際應(yīng)用場景中也可以參考并加入數(shù)據(jù)清洗的流程中。

3.用戶 Session 構(gòu)建

基于上面生成的訂單信息 DF 我們可以結(jié)合 type 和 action_time 截取用戶行為 Session,實戰(zhàn)中 Alibaba 的 Session Gap 推薦為 1h,除此之外還需要結(jié)合 use_type 即可用訂單類型:

    session_list = get_session(action_data, use_type=[1, 2, 3, 5])

下面詳細看下 get_session 方法的實現(xiàn):

def get_session(action_data, use_type=None):
    if use_type is None:
        use_type = [1, 2, 3, 5]
    # 選擇指定 use_type
    action_data = action_data[action_data['type'].isin(use_type)]
    # 由低到高升序排列,按 user 用戶、action_time 行為時間排列
    action_data = action_data.sort_values(by=['user_id', 'action_time'], ascending=True)
    # 按 user_id 聚合為 list
    group_action_data = action_data.groupby('user_id').agg(list)
    # 根據(jù) cut_session 函數(shù)按行處理
    session_list = group_action_data.apply(cnt_session, axis=1)
    return session_list.to_numpy()

這里邏輯也很清晰:

A.首先過濾原始數(shù)據(jù)中不符合的類型的 type 對應(yīng)的訂單

B.根據(jù) user_id 和 action_time 為用戶構(gòu)建時序訂單

深度學習 - 40. N-Gram 采樣與 Session 數(shù)據(jù)獲取 For EGES

C.將 user_id 的行為聚合為 list 供后續(xù)處理

深度學習 - 40. N-Gram 采樣與 Session 數(shù)據(jù)獲取 For EGES

?D.通過 cut_session 方法切分生成 Session

def cnt_session(data, time_cut=30, cut_type=2):
    # 商品、時間、類型列表
    sku_list = data['sku_id']
    time_list = data['action_time']
    type_list = data['type']

    # 構(gòu)建 Session
    session = []
    tmp_session = []
    # 遍歷每一個 Item 即 sku_id
    for i, item in enumerate(sku_list):
        # A.cut_type=2 即下單 B.Session Gap > 30min C.最后一個行為
        if type_list[i] == cut_type \
                or (i < len(sku_list) - 1 and (time_list[i + 1] - time_list[i]).seconds / 60 > time_cut) \
                or i == len(sku_list) - 1:
            tmp_session.append(item)
            session.append(tmp_session)
            tmp_session = []
        else:
            tmp_session.append(item)
    return session

這里對每個用戶的 sku_id list 進行處理,其中設(shè)置了 3 個截斷條件用于結(jié)束 session 并添加到 session 候選集:

? cut_type=2?當前訂單行為為下單

? time_cut > 30 前后訂單超過預(yù)定閾值

? last_order 用戶 list 最后一個訂單

深度學習 - 40. N-Gram 采樣與 Session 數(shù)據(jù)獲取 For EGES

Tips:

通過上面的聚合與處理我們將用戶原始訂單信息生成為每一個用戶多個 Session 的情況,論文中使用 Session 也基于如下考慮:

??計算用戶完整歷史行為的計算與空間成本太高

??用戶的興趣會隨著時間的推移而變化

? 不同的 Session 內(nèi)用戶的興趣可能更加相近,從而強化 item 之間的相似性

三.構(gòu)造 sku_id 游走序列

通過前面劃分好的 Session,后續(xù)我們就可以基于 Session 內(nèi)的 item 商品序列構(gòu)建 Graph 實現(xiàn) GraphEmbedding 前置的游走工作,下面提供 RandomWalk 隨機游走和 Node2vec 兩種游走方式的實現(xiàn)。

1.獲取完整 Session List

    session_list_all = []
    for item_list in session_list:
        for session in item_list:
            if len(session) > 1:
                session_list_all.append(session)

遍歷全部 Session,保留 Session 內(nèi) Item 數(shù)量大于 1 的會話。

2.統(tǒng)計 sku_id 轉(zhuǎn)移詞頻

    node_pair = dict()
    for session in session_list_all:
        # 針對 (t,v) 統(tǒng)計轉(zhuǎn)移頻率
        for i in range(1, len(session)):
            if (session[i - 1], session[i]) not in node_pair.keys():
                node_pair[(session[i - 1], session[i])] = 1
            else:
                node_pair[(session[i - 1], session[i])] += 1

這里對 Session 內(nèi)每個 (Node, Node) 進行詞頻統(tǒng)計。

    # 出節(jié)點、入節(jié)點 (t, v): weight
    in_node_list = list(map(lambda x: x[0], list(node_pair.keys())))
    out_node_list = list(map(lambda x: x[1], list(node_pair.keys())))
    weight_list = list(node_pair.values())
    graph_df = pd.DataFrame({'in_node': in_node_list, 'out_node': out_node_list, 'weight': weight_list})
    graph_df.to_csv('./data_cache/graph.csv', sep=' ', index=False, header=False)

基于上面的詞頻生成節(jié)點轉(zhuǎn)移表格,相當于生成節(jié)點轉(zhuǎn)移的帶權(quán)圖的原始數(shù)據(jù),weight 權(quán)重以節(jié)點出現(xiàn)的頻次為準。

深度學習 - 40. N-Gram 采樣與 Session 數(shù)據(jù)獲取 For EGES

為了方便后續(xù)快速使用,這里將原始的帶權(quán)圖信息存儲至 csv,后續(xù)可以直接加載避免多次數(shù)據(jù)預(yù)處理。

3.構(gòu)建 sku_id 圖

    # networkx 讀取生成帶權(quán)圖
    G = nx.read_edgelist('./data_cache/graph.csv', create_using=nx.DiGraph(), nodetype=None, data=[('weight', int)])
    walker = RandomWalker(G, p=args.p, q=args.q)
    # 生成 Alias 轉(zhuǎn)移概率表
    print("Preprocess transition probs...")
    walker.preprocess_transition_probs()

這里使用 networkx 讀取上面的數(shù)據(jù)生成帶權(quán)圖,再定義?RandomWalker 類,其實現(xiàn)如下:

class RandomWalker:
    def __init__(self, G, p=1, q=1):
        """
        :param G:
        :param p: Return parameter,controls the likelihood of immediately revisiting a node in the walk.
        :param q: In-out parameter,allows the search to differentiate between “inward” and “outward” nodes
        """
        self.G = G
        self.p = p
        self.q = q

    def deepwalk_walk(self, walk_length, start_node):

        walk = [start_node]

        while len(walk) < walk_length:
            cur = walk[-1]
            cur_nbrs = list(self.G.neighbors(cur))
            if len(cur_nbrs) > 0:
                walk.append(random.choice(cur_nbrs))
            else:
                break
        return walk

    def node2vec_walk(self, walk_length, start_node):

        G = self.G
        alias_nodes = self.alias_nodes
        alias_edges = self.alias_edges

        walk = [start_node]

        while len(walk) < walk_length:
            cur = walk[-1]
            cur_nbrs = list(G.neighbors(cur))
            if len(cur_nbrs) > 0:
                if len(walk) == 1:
                    walk.append(
                        cur_nbrs[alias_sample(alias_nodes[cur][0], alias_nodes[cur][1])])
                else:
                    prev = walk[-2]
                    edge = (prev, cur)
                    next_node = cur_nbrs[alias_sample(alias_edges[edge][0],
                                                      alias_edges[edge][1])]
                    walk.append(next_node)
            else:
                break

        return walk

    def simulate_walks(self, num_walks, walk_length, workers=1, verbose=0):

        G = self.G

        nodes = list(G.nodes())

        results = Parallel(n_jobs=workers, verbose=verbose, )(
            delayed(self._simulate_walks)(nodes, num, walk_length) for num in
            partition_num(num_walks, workers))

        walks = list(itertools.chain(*results))

        return walks

    def _simulate_walks(self, nodes, num_walks, walk_length, ):
        walks = []
        for _ in range(num_walks):
            random.shuffle(nodes)
            for v in nodes:
                if self.p == 1 and self.q == 1:
                    walks.append(self.deepwalk_walk(
                        walk_length=walk_length, start_node=v))
                else:
                    walks.append(self.node2vec_walk(
                        walk_length=walk_length, start_node=v))
        return walks

    def get_alias_edge(self, t, v):
        """
        compute unnormalized transition probability between nodes v and its neighbors give the previous visited node t.
        :param t:
        :param v:
        :return:
        """
        G = self.G
        p = self.p
        q = self.q

        unnormalized_probs = []
        for x in G.neighbors(v):
            weight = G[v][x].get('weight', 1.0)  # w_vx
            if x == t:  # d_tx == 0
                unnormalized_probs.append(weight / p)
            elif G.has_edge(x, t):  # d_tx == 1
                unnormalized_probs.append(weight)
            else:  # d_tx > 1
                unnormalized_probs.append(weight / q)
        norm_const = sum(unnormalized_probs)
        normalized_probs = [
            float(u_prob) / norm_const for u_prob in unnormalized_probs]

        return create_alias_table(normalized_probs)

    def preprocess_transition_probs(self):
        """
        Preprocessing of transition probabilities for guiding the random walks.
        """
        G = self.G

        alias_nodes = {}
        for node in G.nodes():
            unnormalized_probs = [G[node][nbr].get('weight', 1.0)  # 保存start的鄰居節(jié)點的權(quán)重
                                  for nbr in G.neighbors(node)]
            norm_const = sum(unnormalized_probs)
            normalized_probs = [
                float(u_prob) / norm_const for u_prob in unnormalized_probs]  # 計算從node到鄰居的轉(zhuǎn)移矩陣
            alias_nodes[node] = create_alias_table(normalized_probs)

        alias_edges = {}

        for edge in G.edges():
            alias_edges[edge] = self.get_alias_edge(edge[0], edge[1])

        self.alias_nodes = alias_nodes
        self.alias_edges = alias_edges

        return

通過調(diào)用 RandomWalker 的 preprocess_transition_probs 方法可以生成對應(yīng) Graph 的 Node Alias 概率轉(zhuǎn)移表與 Edge Alias 轉(zhuǎn)移表,基于轉(zhuǎn)移表與 Alias 采樣就可以進行后續(xù)的游走序列生成了。這里 RandomWalker 包含了兩個參數(shù) p、q 其實是 Node2vec 中定義游走偏向 BFS 還是 DFS 的參數(shù),如果 p=q=1 則游走退化為簡單的隨機游走。

4.游走構(gòu)造 sku 序列

    # Parallel 多線程實現(xiàn) Session 內(nèi)的 Item 序列游走, P=Q=1 時為 DeepWalk,反之為 Node2vec
    session_reproduce = walker.simulate_walks(num_walks=args.num_walks, walk_length=args.walk_length, workers=4,
                                              verbose=1)
    # 保留長度大于2的游走序列
    session_reproduce = list(filter(lambda x: len(x) > 2, session_reproduce))

這里使用了 Python 的多線程方式加速序列生成的速度并保留長度大于2的游走序列。

? simulate_walks

    def simulate_walks(self, num_walks, walk_length, workers=1, verbose=0):

        G = self.G

        nodes = list(G.nodes())

        results = Parallel(n_jobs=workers, verbose=verbose, )(
            delayed(self._simulate_walks)(nodes, num, walk_length) for num in
            partition_num(num_walks, workers))

        walks = list(itertools.chain(*results))

        return walks

該方法通過 Graph 獲取全部 Nodes,隨后使用 Parallel 多線程執(zhí)行序列游走生成方法,真實調(diào)用的是 _simulate_walks,兩個方法相差一個 "_" 。

? _simulate_walks

    def _simulate_walks(self, nodes, num_walks, walk_length, ):
        walks = []
        for _ in range(num_walks):
            random.shuffle(nodes)
            for v in nodes:
                if self.p == 1 and self.q == 1:
                    walks.append(self.deepwalk_walk(
                        walk_length=walk_length, start_node=v))
                else:
                    walks.append(self.node2vec_walk(
                        walk_length=walk_length, start_node=v))
        return walks

如前面所說,當 p=q=1 時,使用 deepwalk 即常規(guī)的隨機游走生成序列,否則采用 node2vec 生成游走序列,最后返回全部游走結(jié)果列表 walks,下圖為部分游走序列,其中 id 代表 sku_id。

深度學習 - 40. N-Gram 采樣與 Session 數(shù)據(jù)獲取 For EGES

四.商品側(cè)信息預(yù)處理

1.讀取商品信息

    # 添加 SideInfo 側(cè)信息
    # 主要包含每個 sku_id 的 brand,shop_id,cate 品牌、店鋪、標簽
    product_data = pd.read_csv(args.data_path + 'jdata_product.csv').drop('market_time', axis=1).dropna()

讀取商品側(cè)信息文件,去除無關(guān)的 'market_time' 列并刪除 Nan 的列,最后將 sku_id 根據(jù)前面得到的 LabelEncoder 進行編碼轉(zhuǎn)化,這里共有?34048 個 sku 商品。

深度學習 - 40. N-Gram 采樣與 Session 數(shù)據(jù)獲取 For EGES

Tips:

這里的 sku_id 還未編碼,所以并不能與前面 LabelEncoder 編碼過的 sku_id 一一對應(yīng)。

2.Left Join 匹配側(cè)信息

    # 采用 LeftJoin 拼接 Product 信息,其中默認值填充 0
    all_skus['sku_id'] = sku_lbe.inverse_transform(all_skus['sku_id'])
    print(str(all_skus.count()))
    sku_side_info = pd.merge(all_skus, product_data, on='sku_id', how='left').fillna(0)

為了 Left Join 為剛才的商品匹配 Side info 側(cè)信息,這里需要首先將 all_skus 的 sku_id 通過 inverse_transform 反編碼為原始狀態(tài),隨后與 product_data 側(cè)信息進行 Left Join 匹配,默認填充值為 0。

深度學習 - 40. N-Gram 采樣與 Session 數(shù)據(jù)獲取 For EGES

匹配后我們就可以得到樣本中出現(xiàn)過的 sku item 的全部側(cè)信息了。

3.Id2Index 構(gòu)建

與 sku_id 同理,brand、shop_id 和 cate 也無法保證連續(xù)性,因此也需要通過 LabelEncoder 進行編碼從而方便后續(xù)的模型訓練。

    # featNum
    feat_num_list = []

    # id2index
    for feat in sku_side_info.columns:
        if feat != 'sku_id':
            lbe = LabelEncoder()
            sku_side_info[feat] = lbe.fit_transform(sku_side_info[feat])
            feat_num_list.append([feat, len(list(lbe.classes_))])
        else:
            sku_side_info[feat] = sku_lbe.transform(sku_side_info[feat])
            feat_num_list.append([feat, len(list(sku_lbe.classes_))])

    sku_side_info = sku_side_info.sort_values(by=['sku_id'], ascending=True)
    sku_side_info.to_csv('./data_cache/sku_side_info.csv', index=False, header=False, sep='\t')

最后緩存至 csv 文件中以備后續(xù)使用,可以看到編碼后各個類型數(shù)據(jù)的數(shù)量:

[['sku_id', 34048], ['brand', 3663], ['shop_id', 4786], ['cate', 80]]

五.基于 Ngram 與 Negative Sample 的樣本生成

1.自定義 Ngram 樣本生成

    all_pairs = get_graph_context_all_pairs(session_reproduce, args.window_size)
    np.savetxt('./data_cache/all_pairs', X=all_pairs, fmt="%d", delimiter=" ")

自定義方法也很好理解,遍歷每一個 Seq 的每一個 Sku,基于中心詞 target sku 構(gòu)建 window_size 的窗口,隨后將 target sku 與 window 范圍內(nèi)的 context sku 構(gòu)成多組 (target, context) 樣本保存下來。

def get_graph_context_all_pairs(walks, window_size):
    all_pairs = []
    # 每一個序列
    for k in range(len(walks)):
        # 每一個 word
        for i in range(len(walks[k])):
            # 添加 Item -> Target 邏輯
            for j in range(i - window_size, i + window_size + 1):
                if i == j or j < 0 or j >= len(walks[k]):
                    continue
                else:
                    all_pairs.append([walks[k][i], walks[k][j]])
    return np.array(all_pairs, dtype=np.int32)

但是常規(guī)方法只生成了正樣本,還需要我們基于 sku 數(shù)量進行全局的負采樣,不過這里 kreas 已經(jīng)提供了現(xiàn)成的 Ngram 帶負采樣的方法,下面我們嘗試一下。

2.keras.preprocessing.sequence.skipgrams 樣本生成

  all_pairs = []
  labels = []

  num_ns = 5
  SEED = 99 

  for seq in session_reproduce[0:1000]:
      skip_grams, ys = tf.keras.preprocessing.sequence.skipgrams(
          seq,
          vocabulary_size=sku_num,
          window_size=args.window_size,
          negative_samples=5)
      all_pairs.extend(skip_grams)
      labels.extend(ys)

all_pairs 存儲所有 (target, context) 對,num_ns 代表負采樣的數(shù)量,一般為 5-20,seq 為 待采樣序列,window_size 為窗口大小,其關(guān)于正樣本的采樣思路與上面的自定義方法一致,不同的是內(nèi)置了負采樣機制,可以直接得到正負樣本。下圖為 skipgrams 采樣得到的 10 個樣本與其對應(yīng) label:

深度學習 - 40. N-Gram 采樣與 Session 數(shù)據(jù)獲取 For EGES

3.tf.random.log_uniform_candidate_sampler 采樣負樣本

細心的小伙伴會發(fā)現(xiàn)上述方法中,如果參數(shù) negative_sampels = 0 時,得到的就全是正樣本對,結(jié)合?tf.random.log_uniform_candidate_sampler 對每一個正樣本進行一次負采樣也未嘗不可。

- 獲取全部正樣本

all_pairs = []
targets, contexts, labels = [], [], []

positive_skip_grams, ys = tf.keras.preprocessing.sequence.skipgrams(
    seq,
    vocabulary_size=sku_num,
    window_size=args.window_size,
    negative_samples=0)

與上面一致,區(qū)別是 negative_samples 參數(shù)設(shè)置為 0 即不采樣負樣本。

- 根據(jù)正樣本獲取負樣本

for target_word, context_word in positive_skip_grams:
    context_class = tf.reshape(tf.constant(int(context_word), dtype='int64'), (1, 1))
    negative_sampling_candidates, _, _ = tf.random.log_uniform_candidate_sampler(
        true_classes=context_class,
        num_true=1,
        num_sampled=num_ns,
        unique=True,
        range_max=sku_num,
        seed=SEED,
        name="negative_sampling")

根據(jù)正樣本的 context_class 采樣 num_ns 個負樣本,詞庫大小由 sku 總數(shù)決定,unique 用于指定負采樣樣本是否可以重復(fù)。

- 構(gòu)建正負樣本與 Labels

    # Build context and label vectors (for one target word)
    negative_sampling_candidates = tf.expand_dims(negative_sampling_candidates, 1)

    context = tf.concat([context_class, negative_sampling_candidates], 0)
    label = tf.constant([1] + [0] * num_ns, dtype="int64")

    # Append each element from the training example to global lists.
    targets.append(target_word)
    contexts.append(context)
    labels.append(label)

一個正樣本與 num_ns 個負樣本,所以 labels 構(gòu)建采用 1 + 0 x ns 的構(gòu)造方式。

Tips:

這里第三種方法主要是介紹一種負樣本采樣方法,相比第二種方式其不夠簡潔,因此后續(xù)模型實戰(zhàn)中,我們的正負樣本與 Label 采用第二種 skipgram 的方法構(gòu)建。

六.總結(jié)

本文涉及到很多細節(jié)內(nèi)容并未完全展示,更詳細的講解可以參考:

- 根據(jù) networkx 獲取生成帶權(quán)圖:GraphEmbedding networks 獲取圖結(jié)構(gòu)

- DeepWalk 隨機游走:GraphEmbedding DeepWalk 圖文詳解

- Alias 采樣:GraphEmbedding Alias 采樣圖文詳解

- Node2vec 序列游走:GraphEmbedding Node2vec 圖文詳解

- EGES 算法分析:EGES 與推薦系統(tǒng)用戶冷啟動

- Parallel 多線程:Python - 多線程 Parallel / Multiprocessing 示例

- 更多推薦算法相關(guān)深度學習:深度學習導讀專欄?

最后感謝??https://github.com/wangzhegeek/EGES?項目的開發(fā)者,上述數(shù)據(jù)預(yù)處理的數(shù)據(jù)以及 utils 工具類大家可以在 Github 項目中獲取。本文主要對 DataProcess 的過程進行了圖文的詳細分析以供大家參考,后續(xù)將基于上述預(yù)處理得到的數(shù)據(jù)通過?Keras 自定義 Word2vec 與 EGES。文章來源地址http://www.zghlxwxcb.cn/news/detail-422226.html

到了這里,關(guān)于深度學習 - 40. N-Gram 采樣與 Session 數(shù)據(jù)獲取 For EGES的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • N-Gram語言模型工具kenlm的詳細安裝教程

    N-Gram語言模型工具kenlm的詳細安裝教程

    【本配置過程基于Linux系統(tǒng)】 下載源代碼: ?編譯: 發(fā)現(xiàn)報錯: ? 系統(tǒng)中沒有cmake,按照錯誤提示,執(zhí)行以下命令: 安裝完成后,再次cmake: ?又報錯: ?找不到boost,那么就下載它: 安裝完成后繼續(xù)cmake,無語,還報錯:? boost依賴包沒裝全,索性全裝了: 對于eigen3這個包

    2024年02月10日
    瀏覽(19)
  • Elasticsearch對數(shù)字,英文字母等的分詞N-gram tokenizer

    Elasticsearch中提供了一個叫N-gram tokenizer的分詞器,官方介紹如下 The? ngram ?tokenizer first breaks text down into words whenever it encounters one of a list of specified characters, then it emits?N-grams?of each word of the specified length. N-grams are like a sliding window that moves across the word - a continuous sequence of charac

    2023年04月16日
    瀏覽(30)
  • 人工智能自然語言處理:N-gram和TF-IDF模型詳解

    人工智能自然語言處理:N-gram和TF-IDF模型詳解

    N-Gram 是一種基于統(tǒng)計語言模型的算法。它的基本思想是將文本里面的內(nèi)容按照字節(jié)進行大小為 N 的滑動窗口操作,形成了長度是 N 的字節(jié)片段序列。 每一個字節(jié)片段稱為 gram,對所有 gram 的出現(xiàn)頻度進行統(tǒng)計,并且按照事先設(shè)定好的閾值進行過濾,形成關(guān)鍵 gram 列表,也就是

    2024年02月16日
    瀏覽(40)
  • 【Chatgpt4 教學】 NLP(自然語言處理)第十一課 n-gram模型原理

    我起/點更新NLP(自然語言處理)——《王老師帶我成為救世主》 (1)--------------------------------------------------------------------------------------- 我:簡要介紹n-gram模型及其優(yōu)缺點; AI: n-gram模型是一種用于語言建模和文本生成的基本模型,它基于一個簡單的假設(shè):一個單詞在出現(xiàn)

    2023年04月19日
    瀏覽(29)
  • 深度學習中的采樣:下采樣,上采樣,欠采樣,過采樣

    下采樣:池化操作就是經(jīng)典的下采樣,將一張圖片縮小,采用不同的方法將像素點合并從而獲得更小分辨率的照片就叫做下采樣。 上采樣:也叫做圖像插值上采樣就和下采樣反過來,將一張照片放大,在像素點之間根據(jù)放大倍數(shù),以插值的形式插入像素值從而達到放大圖像的

    2024年02月14日
    瀏覽(23)
  • 深度學習上采樣下采樣概念以及實現(xiàn)

    #pic_center =400x 系列文章: 【深度學習】上采樣,下采樣,卷積 torch.nn.functional.interpolate函數(shù) 上采樣 簡單說將圖片放大,通過在像素鍵插入數(shù)據(jù) 1.插值,一般使用的是雙線性插值,因為效果最好,雖然計算上比其他插值方式復(fù)雜,但是相對于卷積計算可以說不值一提,其他插

    2024年02月03日
    瀏覽(21)
  • 深度強化學習經(jīng)驗回放(Experience Replay Buffer)的三點高性能修改建議:隨機采樣、減少保存的數(shù)據(jù)量、簡化計算等

    深度強化學習經(jīng)驗回放(Experience Replay Buffer)的三點高性能修改建議:隨機采樣、減少保存的數(shù)據(jù)量、簡化計算等

    高性能的 ReplayBuffer 應(yīng)該滿足以下三點: 隨機采樣 random sample 的速度要快,盡可能加 快讀取速度(最為重要) 減少保存的數(shù)據(jù)量, 增加吞吐效率 (對分布式而言重要) 保存能 簡化計算 的變量(對特定算法而言重要) 為了達成以上要求,我建議做出以下修改: 把 Replay B

    2024年02月16日
    瀏覽(19)
  • 機器學習深度學習中的上采樣技術(shù)

    在圖像處理中,上采樣主要用于放大圖像,增加圖像的尺寸或分辨率。 上采樣的實質(zhì)是插值或填充新的數(shù)據(jù)點來增加采樣點的數(shù)量。一種常見的上采樣方法是 使用插值技術(shù) (如雙線性插值、三次樣條插值等)來估算新像素的值。在神經(jīng)網(wǎng)絡(luò)中,上采樣也常用于進行 反卷積操

    2024年04月16日
    瀏覽(26)
  • UE引擎開啟DLSS(深度學習超級采樣)

    UE引擎開啟DLSS(深度學習超級采樣)

    首先打開·NVIDIA官方網(wǎng)站 Getting Started with DLSS 從下面的鏈接里面找到unreal版本的DLSS ?根據(jù)提供的幾個版本去下載指定版本的壓縮包(另外在上面也提供了Unity版本的壓縮包) 解完壓縮包后將其解壓到插件目錄下面去 ?然后啟動UE5 ?開啟插件,在設(shè)置里面打開 可以看到,有質(zhì)量

    2024年02月12日
    瀏覽(20)
  • AI:40-基于深度學習的森林火災(zāi)識別

    AI:40-基于深度學習的森林火災(zāi)識別

    ?? 本文選自專欄:AI領(lǐng)域?qū)?從基礎(chǔ)到實踐,深入了解算法、案例和最新趨勢。無論你是初學者還是經(jīng)驗豐富的數(shù)據(jù)科學家,通過案例和項目實踐,掌握核心概念和實用技能。每篇案例都包含代碼實例,詳細講解供大家學習。 ??????本專欄包含以下學習方向: 機器學習、

    2024年02月06日
    瀏覽(20)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包