【问题标题】:How to one-hot-encode sentences at the character level?如何在字符级别对句子进行一次热编码?
【发布时间】:2017-09-22 21:57:37
【问题描述】:

我想将一个句子转换为一个单热向量数组。 这些向量将是字母表的 one-hot 表示。 如下所示:

"hello" # h=7, e=4 l=11 o=14

会变成

[[0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
 [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]

不幸的是,来自 sklearn 的 OneHotEncoder 不作为输入字符串。

【问题讨论】:

  • 到目前为止你尝试过什么?给我们看一些代码!
  • 欢迎来到 StackOverflow。请阅读并遵循帮助文档中的发布指南。 on topichow to ask 在这里申请。 StackOverflow 不是设计、编码、研究或教程服务。
  • 也就是说,请参阅有关 chrord 方法的文档。
  • 到目前为止我尝试的是以下(应用于语料库中的每个句子)但我想知道是否存在更简单的解决方案 sentence_chars = [c for c in sentence.lower() if c in字母表] ohv = label_binarize(sentence_chars, classes=list(alphabet)) ohv = ohv.astype(bool)
  • 来自 sklearn 的 OneHotEncoder 现在已与 CategoricalEncoder 合并,因此现在应该可以使用 sklearn.preprocessing.OneHotEncoder(categories="auto") 来实现。 (这是 LSTM 等顺序模型的默认表示)github.com/scikit-learn/scikit-learn/blob/…

标签: python pandas numpy nlp one-hot-encoding


【解决方案1】:

只需将您传递的字符串中的字母与给定的字母进行比较:

def string_vectorizer(strng, alphabet=string.ascii_lowercase):
    vector = [[0 if char != letter else 1 for char in alphabet] 
                  for letter in strng]
    return vector

请注意,使用自定义字母表(例如“defbcazk”,列将按照每个元素出现在原始列表中的顺序进行排序)。

string_vectorizer('hello')的输出:

[[0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]

【讨论】:

    【解决方案2】:

    这是循环神经网络中的一项常见任务,如果您想使用它,tensorflow 中有专门用于此目的的特定功能。

    alphabets = {'a' : 0, 'b': 1, 'c':2, 'd':3, 'e':4, 'f':5, 'g':6, 'h':7, 'i':8, 'j':9, 'k':10, 'l':11, 'm':12, 'n':13, 'o':14}
    
    idxs = [alphabets[ch] for ch in 'hello']
    print(idxs)
    # [7, 4, 11, 11, 14]
    
    # @divakar's approach
    idxs = np.fromstring("hello",dtype=np.uint8)-97
    
    # or for more clear understanding, use:
    idxs = np.fromstring('hello', dtype=np.uint8) - ord('a')
    
    one_hot = tf.one_hot(idxs, 26, dtype=tf.uint8)
    sess = tf.InteractiveSession()
    
    In [15]: one_hot.eval()
    Out[15]: 
    array([[0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
           [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
           [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
           [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
           [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=uint8)
    

    【讨论】:

    • 为什么我们必须减去 97?我发现 one_hot 没有它就无法正常工作......
    • @gregoruar '因为 97 是字母开头的 ASCII 码(即a)。请在此处查看此页面:theasciicode.com.ar/ascii-printable-characters/… 了解更多详情
    【解决方案3】:

    对于 pandas,您可以通过传递分类系列来使用 pd.get_dummies:

    import pandas as pd
    import string
    low = string.ascii_lowercase
    
    pd.get_dummies(pd.Series(list(s)).astype('category', categories=list(low)))
    Out: 
       a  b  c  d  e  f  g  h  i  j ...  q  r  s  t  u  v  w  x  y  z
    0  0  0  0  0  0  0  0  1  0  0 ...  0  0  0  0  0  0  0  0  0  0
    1  0  0  0  0  1  0  0  0  0  0 ...  0  0  0  0  0  0  0  0  0  0
    2  0  0  0  0  0  0  0  0  0  0 ...  0  0  0  0  0  0  0  0  0  0
    3  0  0  0  0  0  0  0  0  0  0 ...  0  0  0  0  0  0  0  0  0  0
    4  0  0  0  0  0  0  0  0  0  0 ...  0  0  0  0  0  0  0  0  0  0
    
    [5 rows x 26 columns]
    

    【讨论】:

      【解决方案4】:

      这是一个使用NumPy broadcasting 的矢量化方法来给我们一个(N,26) 形状的数组 -

      ints = np.fromstring("hello",dtype=np.uint8)-97
      out = (ints[:,None] == np.arange(26)).astype(int)
      

      如果您正在寻找性能,我建议使用初始化数组然后分配 -

      out = np.zeros((len(ints),26),dtype=int)
      out[np.arange(len(ints)), ints] = 1
      

      示例运行 -

      In [153]: ints = np.fromstring("hello",dtype=np.uint8)-97
      
      In [154]: ints
      Out[154]: array([ 7,  4, 11, 11, 14], dtype=uint8)
      
      In [155]: out = (ints[:,None] == np.arange(26)).astype(int)
      
      In [156]: print out
      [[0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
       [0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
       [0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
       [0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
       [0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0]]
      

      【讨论】:

        【解决方案5】:

        您询问了“句子”,但您的示例仅提供了一个单词,因此我不确定您想对空格做什么。但就单个单词而言,您的示例可以通过以下方式实现:

        def onehot(ltr):
         return [1 if i==ord(ltr) else 0 for i in range(97,123)]
        
        def onehotvec(s):
         return [onehot(c) for c in list(s.lower())]
        
        onehotvec("hello")
        [[0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
         [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
         [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
         [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
         [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
        

        【讨论】:

          猜你喜欢
          • 2020-06-14
          • 1970-01-01
          • 2020-11-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-09-27
          • 2021-02-10
          相关资源
          最近更新 更多