当前位置:   article > 正文

机器学习——词向量模型(CBOW代码实现-逻辑顺利,预测准确率为0,暂告一段落)_在cbow中词向量是如何初始化的

在cbow中词向量是如何初始化的

本来是不打算做这个CBOW代码案例的,想快马加鞭看看前馈神经网络
毕竟书都买好了
可是…可是…我看书的时候,感觉有点儿困难,哭的很大声…
感觉自己脑细胞可能无法这么快接受
要不,还是退而求个稍微难度没那么大的事,想想自己还有什么是没实现的呢
哦!CBOW的案例还没做呢~
在一个巨人面前,我无耻地选择了暂避其锋芒
就好像,我本应该英勇地迈过刀山火海,可是我却怂了
而且,怂的有理有据:CBOW还没实现呢
只希望,CBOW案例,不要太难,不然我根本寸步难行,只能天天打游戏聊以自慰

首先,我计划根据一个客服语料,然后用CBOW去预测某个中间关键词

目标明确后,问题接踵而至

问题1-能否用中文语料:不行,因为中文分词很麻烦,我懒得去搞分词,重点是CBOW
英文语料很简单,因为英文是一个词跟另一个词,用空格分开,获取十分简单

问题2-头尾单词怎么解决:毕竟CBOW是获取关键词的前c个和后c个单词来训练的,但开头单词没有前c个单词,末尾单词没有后c个单词
解决办法:用额外的单词替代,比如None,应该问题不大的吧

问题3-按句还是按所有句取上下文:如果是按句取上下文,那么一个句子开头和末尾单词的下文就是None,语料文件有很多个句子,就会有很多个None。
如果按所有句取上下文,那整个语料文件就只有开头有None,末尾有None,None数量很少
解决办法:还是按句吧,毕竟两句之间的上下文,是毫无关系的。

按照【基于HierarchicalSoftmax的CBOW】正反向传播流程,来设计程序吧!

【基于HierarchicalSoftmax的CBOW】正向传播过程

  • 输入层:
    • 转换独热编码:将词典D转换为one-hot独热编码,
    • 获取上下文:按规定上下文的长度k,来截取语库C里的上下文单词 x x x和预测单词 y ∗ y* y
    • 获取独热编码:获取上下文单词x的独热编码向量 x 1 x1 x1, x 2 x2 x2, x 3 x3 x3, x 4 x4 x4,作为初始输入矩阵X=[ x 1 x1 x1, x 2 x2 x2, x 3 x3 x3, x 4 x4 x4]
  • 投影层:
    • 计算中间向量:
      • 将初始矩阵X乘以一个权重矩阵W,提取出各个初始向量 x 1 x1 x1, x 2 x2 x2, x 3 x3 x3, x 4 x4 x4的权重系数 w 1 w1 w1 w 2 w2 w2 w 3 w3 w3 w 4 w4 w4
      • 将这些权重系数加和,作为中间向量h=[ w 1 w1 w1+ w 2 w2 w2+ w 3 w3 w3+ w 4 w4 w4],注意,这里的加和是按列加和
  • 输出层:
    • 构建huffman树,
    • 计算路径概率
    • 计算预测模型

其次,要先进行数据结构设计,总不能用向量吧,因为每个单词,都有对应的独热编码

有对应关系的,可以用字典、也可以用pandas的dataframe的二维结构数据

考虑到dataframe有较多的计算操作语法,或许会更加简洁,不需要自己另外设计各种计算的操作方式。

所以,能用dataframe的就尽量多用dataframe吧

输入层:

  • dataframe:
    • 所有单词的独热编码
    • 选取的上下文独热编码

投影层:

  • dataframe:
    • 每个单词潜在特征的向量组成的矩阵W(词向量)
    • 选取的上下文词向量
    • 中间向量h(上下文的词向量之和)

输出层:

  • 二叉树节点:
    • 矩阵:每个节点上的θ值
      至于构建huffman树,打算是构建一个二叉树对象,然后每个节点上的θ用矩阵表示

暂定这样吧。

输入层

输入层,需要给投影层输入一个上下文里每个单词的独热编码
但首先,要先有语料C,才能依次获取上下文进行训练
我在想,到底是每次获取一个上下文进行训练,还是一次性把所有上下文都获取了再训练。
。。。。每次训练一个上下文,会不会要训练很久
。。。。可是,要获取所有的上下文,那就相当于语料C如果总共有1000个单词,那上下文就会有1000个向量构成的矩阵了,量会不会太大了呢?
不如每次获取一个,然后每次都训练一个

  • 问题来了:每次训练一个上下文,那这个上下文要训练到底,还是说要等所有上下文都训练一次后,再统一反向传播去迭代模型参数呢?
  • 很显然,肯定是要所有上下文都训练一次后,再反向传播
  • 所以上下文的训练是按批次来进行的
    • 第一批:
      • 正向传播:所有上下文依次训练第一次
      • 反向传播:模型参数迭代第一次
    • 第二批:
      • 正向传播:所有上下文依次训练第二次
      • 反向传播:模型参数迭代第二次

词典D转独热编码

  • 从语料中得到一个不含重复单词的词典D
  • 将词典D中所有单词转换成独热编码矩阵
    在这里插入图片描述

获取单个上下文的独热编码

现在要从语料C种,获取一个上下文,但考虑到依次获取所有上下文
所以需要循环获取上下文
另外,先规定一下,上下文的n为4,也就是一个上下文的上文为2,下文为2,另外要预测上下文中间的单词,所以总共要获取的上下文和待预测单词,就是5
上文单词(2个)+待遇测中间单词(1个)+下文单词(2个)

获取上下文的独热编码

获取4个上下文的独热编码
在这里插入图片描述

投影层:

  • dataframe:
    • 每个单词潜在特征的向量组成的矩阵W(词向量)
    • 选取的上下文词向量
    • 中间向量h(上下文的词向量之和)

创建词向量矩阵W

>每个单词,都有其多个维度的特征(比如褒贬、
每个单词的特征维度数,由我们自己决定。
我决定,假设每个单词由3个维度来决定(具体是什么维度,其实我也不知道,这个要交给神经网络去自动计算迭代里边的数值)

那么所有单词,都有自己的词向量
假设D词典里的单词数为N,词向量维度为3,所有单词的词向量矩阵就是一个Nx3的矩阵
我们将这个矩阵里的每个值,都初始化为1

  • 然后获取单个上下文的词向量矩阵如下
    在这里插入图片描述

计算单个上下文的中间向量h

在这里插入图片描述

输出层

构造huffman树

在这里插入图片描述

实操过程困惑1:如果W和θ初始值都设为1,迭代后,输出的W值一样

不理解,为什么一个单词里的词向量,三个值都一样呢?
值一样那还有什么意义?
但思考了一下原本W迭代思路,确实也没看出它的三个值会有区别的计算
但。。。该怎么办呢?值都一样,是没意义的,难道是我对于CBOW的原理思考有点儿问题?
唉。。。回去再看看。。。

实操困惑解决:W和θ的初始化,都用随机数(我后来用了随机正太分布值)
我以为只要参数进入训练,就可以自动调参并往好的方向发展
但现在看来,不太像。
现在让参数随机初始化,就像是给了随机化的数值,然后随机数值与随机数值之间进行关系的重组计算。

这就好像是,如果一群男的和一群男的,无论经过多少次迭代计算,都一定生不出小孩
但如果我随机设置性别,那一群男女和一群男女,经过多次迭代计算,应该能计算出生小孩的最大概率组合
如果是这么个意思,那我之前对于W词向量的特征理解就有误了。
我原以为词向量是对一个单词的潜在语义的数值表示,比如褒贬义、情感色彩、动名词等描述一个单词的特征数值,但现在看来并不是。
现在在CBOW训练下的词向量,只是纯粹的随机值,经过迭代后能够结合其他单词的词向量一起,更好地预测中心单词,仅此而已。
并且不同的初始随机值,最终训练出来的词向量W都未必是一样的。

百度了很久,有up主提到scikit-learn还是什么官方包,在初始化时用的是正态分布随机数来初始化的。

但没人能告诉我,为什么参数W要用正态分布的随机数来进行初始化。

没办法,只能自己进行一下合理的猜测。

首先,中间向量h是根据上下文的词向量W相加而成。
如果W词向量的每一项数值都是服从同一个(0,1)的正态分布,那么h向量里的每一个数值也都是服从同一个(0,1)正态分布的。
也就是,h向量里的每一项都是围绕0上下浮动的,且总和加起来有可能大于0,也有可能小于0

那么,当中间向量h,进入huffman里,与每个节点的θ进行sigmoid的概率计算。

P_右子树 = sigmoid(h*θ)

假设单个节点的θ向量里的每一项都是1,而h向量里的每一项都服从同一个(0,1)正态分布

那么h与θ的点乘,就会围绕在0上下,且有可能大于0,也有可能小于0。

那这样的话,根据sigmoid函数特点,当前节点计算出来的sigmoid值,也就围绕在0.5上下。

  • 即当h*θ大于0时,sigmoid值就大于0.5,此时的sigmoid值表示进入右子树的概率
  • 当h*θ小于0时,sigmoid值就小于0.5,此时的1-sigmoid值就表示进入左子树的概率

所以,如果我们把词向量W用服从正态分布的随机数来初始化,那么在进入huffman树进行每一层的节点选择时,左子树和右子树的概率就相对比较均衡(即,既有可能进入左子树,也有可能进入右子树,避免我们自己人为设定固定值造成模型一开始有较大的偏差)

这是我自己猜测下,目前认为比较合理的
但也有可能后期打脸,到时候脸疼了再说吧

眼泪哗哗哗哗地流,之前一直出问题
周六下午闲暇无聊,排了一下bug!
终于发现问题了,呜呜呜呜呜呜tmd,列表不能直接赋值,我早该想到的。。。py的列表唉
排完bug,做了一系列检查
首先看看,每个待预测单词路径下,每个经过的节点的一些属性值,尤其是θ值,可以看到是经过迭代的
在这里插入图片描述
第二个检查是W的检查,W也发生了迭代,但因为迭代次数少,所以可能不那么明显


  • 1

在这里插入图片描述
在这里插入图片描述

当前代码&思路

import math
import numpy as np
from docx import Document
import re
import pandas as pd
import random

pd.options.display.max_rows = None
"""
需要提前设置的参数:doc_path语料的word文档、η学习率、词向量的维度W_columns、iterate_times迭代次数、context_word_num单个上下文的词数量
+++++++ 【W词向量的所有初始值、θ霍夫曼树非叶子节点上的权重参数】:这两个关键参数在后续用正态分布随机树来进行初始化 ++++
"""
doc_path = r"trainingword.docx"
η = 0.1
W_columns = 20
iterate_times = 100
context_word_num = 4

# 获取语料库C+统计无重复单词的词典D
doc = Document(doc_path)
C_list = []
all_text = ''
for i in doc.paragraphs:
    if len(i.text) != 0:
        para = [x for x in re.split(' |!|\?|\.|。|,|,|\(|\)', i.text) if x]
        C_list.append(para)
        all_text = all_text + i.text
words_org = [x for x in re.split(' |!|\?|\.|。|,|,|\(|\)', all_text) if x]
"""缺失单词设为aaa,以便上下文开头结尾处缺失"""
# replace_word = 'aaa'
# words_org.append(replace_word)

"""词典D转独热编码"""
D_list = set(words_org)
N = len(D_list)
D_onehot = {}
for index, value in enumerate(D_list):
    temp = [0] * N
    temp[index] = 1
    D_onehot[value] = temp
    del temp
# 最终词典D的独热编码为D_df
D_df = pd.DataFrame(D_onehot)

"""初始化词向量矩阵W:W_columns个维度特征"""
# 这意味着后续的中间向量h和huffman树上的θ向量,分别都是用3个值表示,如 h=[1,10,20]
W_dict = {}
for index, word in enumerate(D_list):
    W_dict[word] = [10*random.gauss(0,1) for i in range(W_columns)]
# 最终词向量用W_df表示
W_df = pd.DataFrame(W_dict)
print(f"初始的词向量W为")
print(W_df)

# 统计每个单词的词频,word_count是series数据类型
word_count = pd.value_counts(words_org)
# word_count.pop(item='aaa')
"""第2阶段huffman树:设置huffman树-节点对象的属性"""


class Node:
    # 一棵huffman树,有几个特征:
    # 根节点:没有d值,没有path值,没有word值
    # 非叶子节点:没有word值
    # 叶子节点:没有θ值,没有left左子树、right右子树
    def __init__(self, value, word):
        self.value = value  # !!!
        self.word = word  # 如果是叶子节点,则存储按权重划分好的最终的某个单词
        self.θ = None  # 待迭代的参数θ
        self.d = None  # 当前节点的编码,是0或1,左节点为0,右节点为1
        self.path = [] # 记录从根节点到当前节点的编码路径,如[0,1,0,1]
        self.left = None  # 左子树!!!
        self.right = None  # 右子树!!!

    """定义输出的魔法函数"""

    def __str__(self):
        return (self.value, self.word)


"""第2阶段huffman树:插入排序堆"""
def insert_sort_node(nodes, node):
    # 如果nodes列表里,没有任何节点了,则表示所有node节点都已经划分完毕,
    # 把最后的一个node作为根节点插入nodes列表后,返回只包含一个根节点的nodes列表。
    if len(nodes) == 0:
        nodes.append(node)
        return nodes
    # 要根据Node对象里的value值(权重),插入nodes列表,并排序
    for index in range(len(nodes) - 1, -1, -1):
        if node.value < nodes[index].value:
            nodes.insert(index + 1, node)
            break
    else:
        nodes.insert(0, node)
    # 查看每次nodes堆变化
    # list1 = [(node.value, node.word) for node in nodes]
    # print(list1)
    return nodes


"""第2阶段huffman树:建huffman树,完成每个node的word单词、d值、value权重值、left左子树、right右子树的属性存储"""


def build_huffman_tree(nodes):
    # huffman树的建立过程:不断地从频次最低(即权重最低)的两个节点开始,合并成新节点
    # ① 初始:将所有单词都按频次,由高到低存储在列表nodes里
    # ② pop取出频次最低的单词及频次值,作为右节点,设置当前右节点的编码值d为0
    # ③ pop再去除频次第二低的单词及频次值,作为左节点,设置当前左节点的编码值d为1
    # ④ 将左右节点的频次值加和,作为一个新节点,插入到nodes列表里,重新排序
    # ⑤ 重复①②③④,但是要注意,第5步合并成新节点node之后,node就不是单词了,而是一个有左右子节点的node,只有权重值(权重值=它的左子节点权重+右子节点权重)
    while len(nodes) > 1:
        node_right = nodes.pop()
        node_right.d = 0
        node_left = nodes.pop()
        node_left.d = 1
        node = Node(node_left.value + node_right.value, None)
        node.left = node_left
        node.right = node_right
        nodes = insert_sort_node(nodes, node)
    else:
        huffman_tree = nodes[0]
        return huffman_tree


"""第2阶段huffman树:遍历huffman树,并依次初始化θ,记录每个单词的huffman树的路径path"""
word_path = {}


def search_huff_tree(node_now, last_path=None):
    # 从根节点,到每一个叶子节点,都遍历一次,顺路存储每个节点(除了根节点外)的θ初始参数和path路径
    node = node_now
    # 当一个node节点的word为空,说明它是非叶子节点,且θ参数为空时,说明它是θ还没有初始化的非叶子节点,这时候才可以对当前node初始化θ
    if node.word == None and node.θ == None:
        node.θ = [random.randint(-5,5) for i in range(W_columns)]
    # 当一个node节点上一个节点last_path不为空时,说明上个节点是有path值的,当前节点node先把上个节点的path继承下来
    if last_path != None:
        node.path = [p for p in last_path]

    if node.word == None:
        # 只要当前节点不是叶子节点,就增加新节点的编码值作为node路径path,
        # 并且还要向下递归,遍历下一个节点,从而开始下一个节点搜索,完成下一个节点的θ值初始化和记录下一个节点path路径,直到所有节点都遍历完
        node.path.append(node.d)
        path = [p for p in node.path]
        search_huff_tree(node.right, path)
        node.path.append(node.d)
        search_huff_tree(node.left,path)
    else:
        # 如果当前节点是叶子节点,那就在当前节点的path里,添加完当前的编码值,形成当前node的path值,然后结束本次搜索
        node.path.append(node.d)
        """所有单词的路径,都存储在列表word_path里"""
        word_path[node.word] = [p for p in node.path]
        return


"""第2阶段huffman树:建立huffman树,并初始化非叶子节点上的参数θ,设置每个非根节点上的d编码值(左1右0)"""
nodes = []
for word_value in word_count.items():
    nodes.append(Node(word_value[1], word_value[0]))
huffman_tree = build_huffman_tree(nodes)
search_huff_tree(huffman_tree)

"""第3阶段反向传播:需要迭代θ和W"""


"""第3阶段反向传播:【根据上个节点的d值,判断下个节点是选左,还是选右(左1右0)】"""
def get_node(next_d, node_now=None):
    if next_d == 0:
        return node_now.right
    elif next_d == 1:
        return node_now.left


def sigmoid(h, θ):
    x = np.matmul(h, θ)
    try:
        result = 1 / (1.0 + math.exp(-x))
    except OverflowError:
        if -x>0:
            result = 1 / (1.0 + math.exp(700))
        elif -x<0:
            result = 1 / (1.0 + math.exp(-700))
    return result


"""第3阶段反向传播:计算单个上下文到预测单词之间的概率总值"""
def single_context_iterate(h, y_word, huffman_tree):
    global η, W_step_value
    path = word_path[y_word]  # 获取当前单词的路径path
    if path[0] == None:
        path.pop(0)

    node = huffman_tree  # node为根节点
    for next_d in path:
        # 注意:根节点是没有d值,所以path里的所有不为0的d,都是当前节点的下一个节点的d值,所以就代号为next_d,表示当前node的下一个应选择的node的d值
        """【下一个节点的d值,表示当前节点的选择方向】"""
        if node.word != None:
            # 当前节点的word值不是空值,说明它是叶子节点,则结束循环
            break
        sig = sigmoid(h, node.θ)
        """迭代当前节点的θ值:十分重要!!!十分关键!!!!"""
        W_single_step_value = [η * (1 - next_d - sig) * θ_value for θ_value in node.θ]
        W_step_value = [x + y for x, y in zip(W_step_value, W_single_step_value)]
        θ_single_step_value = η * (1 - next_d - sig)*h
        node.θ = [x + y for x, y in zip(node.θ, θ_single_step_value)]
        node = get_node(next_d, node)
    return W_step_value

"""第3阶段反向传播:把所有上下文存进列表里"""
# 由于我们要迭代很多次,所以每次都重新选取上下文,会非常耗时
# 因此,不如一次性,把所有的上下文都选取后,放进一个列表里边
# 这样,以后无论迭代多少次,上下文都是一样的,不需要重复选取
c = context_word_num//2
y_and_context_list = []
for sentence in C_list:
    for index, word in enumerate(sentence):
        """获取单个上下文"""
        y = word
        context = []
        if index-2>=0:
            context.append(sentence[index-1])
        if index-2>=0:
            context.append(sentence[index-2])
        if index+1<len(sentence):
            context.append(sentence[index+1])
        if index+2<len(sentence):
            context.append(sentence[index+2])
        """计算单个上下文的中间向量h"""
        y_and_context = (y, context)
        y_and_context_list.append(y_and_context)

"""第3阶段反向传播:根据每个上下文和对应的待预测单词y,去迭代θ"""
for i in range(iterate_times):
    print(f"第{i + 1}次迭代")
    for y_and_context in y_and_context_list:
        y, context = y_and_context
        if y == 'aaa':
            print('aaa也可以吗!')
            raise Exception
        """计算单个上下文的中间向量h"""
        h = W_df[context].sum(axis=1)
        W_step_value = [0.0]*W_columns  # W的迭代公式,是需要对同一条路径下每个节点的迭代值加和后,再进行迭代的,所以需要这个中间值,表示迭代值加和
        """计算每个上下文,到达待预测单词之间的每一个节点上的概率总值,并迭代每个θ值"""
        W_step_value = single_context_iterate(h, y, huffman_tree)

        """迭代当前的上下文里,每个单词的词向量W"""
        for word in context:
            W_df[word] += [step_value/W_columns for step_value in W_step_value]
print(f"迭代后的词向量W为")
print(W_df)

"""第3阶段的检查:根据每个待预测单词的path路径-依次查看每个路径的每个节点上的属性值"""
def check_path_para(node_now):
    next_d = next(g)
    print(f"next_d值为{next_d},word值为{node_now.word},权重{node_now.value},θ为{node_now.θ}")
    if next_d == 1:
        node_now = node_now.left
    else:
        node_now = node_now.right
    # 如果下一个节点是叶子节点,就返回,否则继续往下递归
    if node_now.word != None:
        return
    check_path_para(node_now)
# 建立一个迭代器,辅助获取每个单词的路径
def get_next_d(y_path):
    for p in y_path:
        yield p
for y_word in D_list:
    y_path = word_path[y_word]
    print(f"当前单词为{y_word},路径为{y_path}")
    g = get_next_d(y_path)
    check_path_para(huffman_tree)



"""第4阶段:检测迭代一定次数后,模型预测正确率"""
# 已知训练好的词向量矩阵为W_df字典、所有待预测单词的正确路径word_path字典、已经训练好的huffman树(含θ)
# 根据单个上下文的词向量来获取中间向量h,然后h进入huffman树,在每个节点上进行左右分岔路的概率计算
    # 进入左子树的概率值为h*θ的1-sigmoid值、进入右子树的概率值为h*θ的sigmoid值
    # 其实只需要判断一个概率值,即可确定下一个节点是左子树or右子树。
    # 例如,如果进入右子树的概率值大于0.5,则让h进入右子树,否则进入左子树
    # 依次循环进行,直到达到叶子节点,获取到依据概率判断得到的预测单词y*为止
    # 若依概率获取到的单词y*与实际待预测单词y不同,则判定为预测错误,预测结果记为0;若y*与y相同,则预测正确,预测结果记为1。最终统计正确率
def get_y_predict(h,node_now):
    node = node_now
    """如果当前节点的word属性不为None的时候,说明已经到达叶子节点,返回叶子节点上的预测单词即可结束迭代"""
    if node.word != None:
        return node.word
    print(f"_______节点+1______")
    """如果未到达叶子节点,则进入迭代,依据右子树的概率sig来判断进入下一节点"""
    θ = node.θ
    sig = sigmoid(h,θ)
    # print(f"θ值为{node.θ}")
    # print(f"h*θ值{np.matmul(h,node.θ)},sig值为{sig}")
    if sig<0.5:
        node_next = node.right
    else:
        node_next = node.left
    return get_y_predict(h,node_next)

result = [] # 记录每个预测结果
y_pre_lst = []
y_real_lst = []
for y_and_context in y_and_context_list:
    node_root = huffman_tree
    y, context = y_and_context
    """获取单个上下文的中间向量h"""
    print("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++")
    # print(f"中间向量h{h},真实单词为{y}")
    print()
    h = W_df[context].sum(axis=1)

    y_pre = get_y_predict(h,node_root)
    if y_pre == y:
        result.append(1)
    else:
        result.append(0)
    y_pre_lst.append(y_pre)
    y_real_lst.append(y)

data_y = pd.DataFrame([y_pre_lst,y_real_lst])
print(data_y)
print(f"最后预测准确率为{sum(result)/len(result)}")


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324

#程序验证的预测准确率,接近于0,不知道为什么,完全不知道该怎么办,找不到任何思路,除了怀疑hierarchical softmax对于参数的迭代公式本身有问题,但那都是论文出来的,怎么可能有问题呢。
头疼,非常头疼,国内的理论一大堆,实践真的寥寥无几
问了GPT-4,唉,句句都有道理,但就是没有落到实处的问题。。。查无所获,

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/523216
推荐阅读
相关标签
  

闽ICP备14008679号