文本哈希技巧在Python和C中产生不同的结果#

2024-04-27 03:47:48 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图将一个经过训练的模型移到生产环境中,在尝试复制C#中Keras hashing_trick()函数的行为时遇到了一个问题。当我对句子进行编码时,我在C语言中的输出与在python中的输出不同:

文本:“信息-配置处理完成。”

Python:[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 217 142 262 113 319 413]

C#:【0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,433,426,425,461,336,146,52]

(从调试器复制,两个序列的长度都为30)

我所做的:

  1. 更改C中文本字节的编码以匹配python字符串.编码()函数默认值(UTF8)
  2. 将字母大写改为小写和大写
  3. 尝试使用转换.ToUInt32而不是位转换器(导致溢出错误)

我的代码(下面)是我的Keras hashing_-trick函数的实现。给出一个输入语句,然后函数将返回相应的编码序列。在

public uint[] HashingTrick(string data)
    {
        const int VOCAB_SIZE = 534; //Determined through python debugging of model
        var filters = "!#$%&()*+,-./:;<=>?@[\\]^_`{|}~\t\n".ToCharArray().ToList();
        filters.ForEach(x =>
        {
            data = data.Replace(x, '\0');
        });
        string[] parts = data.Split(' ');
        var encoded = new List<uint>();
        parts.ToList().ForEach(x =>
        {

            using (System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create())
            {
                byte[] inputBytes = System.Text.Encoding.UTF8.GetBytes(x);
                byte[] hashBytes = md5.ComputeHash(inputBytes);


                uint val = BitConverter.ToUInt32(hashBytes, 0);
                encoded.Add(val % (VOCAB_SIZE - 1) + 1);
            }
        });
        return PadSequence(encoded, 30);

    }
    private uint[] PadSequence(List<uint> seq, int maxLen)
    {
        if (seq.Count < maxLen)
        {
            while (seq.Count < maxLen)
            {
                seq.Insert(0, 0);
            }
            return seq.ToArray();
        }
        else if (seq.Count > maxLen)
        {
            return seq.GetRange(seq.Count - maxLen - 1, maxLen).ToArray();
        }
        else
        {
            return seq.ToArray();
        }
    }

散列技巧的keras实现可以找到here

如果有帮助的话,我正在使用ASP.NETwebapi作为我的解决方案类型。在


Tags: 函数文本编码datareturncountsystemseq
2条回答

我没有解决试图与C斗争以获得哈希的问题,而是采用了不同的方法来解决这个问题。当我制作数据集来训练模型(这毕竟是一个机器学习项目)时,我决定使用@Jeron Mostert的哈希函数实现在将数据集输入模型之前对其进行预哈希。在

这个解决方案更容易实现,最终的工作效果和原始文本哈希一样好。对于那些像我这样尝试跨语言哈希的人来说,一句忠告:不要这样做,这会让人头疼!使用一种语言来散列文本数据,并找到一种方法来创建一个包含所有所需信息的有效数据集。在

代码最大的问题是它没有考虑到Python的int是任意精度的整数,而C的uint只有32位。这意味着Python正在计算hash中所有128位的模,而C没有(而且BitConverter.ToUInt32在任何情况下都是错误的,因为endianness是错误的)。另一个问题是\0不能终止C中的字符串,而且{}不能在不改变结果的情况下直接添加到MD5哈希中。在

以尽可能直接的方式翻译:

int[] hashingTrick(string text, int n, string filters, bool lower, string split) {
    var splitWords = String.Join("", text.Where(c => !filters.Contains(c)))
        .Split(new[] { split }, StringSplitOptions.RemoveEmptyEntries);

    return (
        from word in splitWords
        let bytes = Encoding.UTF8.GetBytes(lower ? word.ToLower() : word)
        let hash = MD5.Create().ComputeHash(bytes)
        // add a 0 byte to force a non-negative result, per the BigInteger docs 
        let w = new BigInteger(hash.Reverse().Concat(new byte[] { 0 }).ToArray())
        select (int) (w % (n - 1) + 1)
    ).ToArray();
}

样品使用:

^{pr2}$

217 142 262 113 319 413

这段代码有各种各样的低效:与使用StringBuilder相比,使用LINQ过滤字符的效率非常低,而且我们在这里并不需要BigInteger,因为MD5总是精确的128位,但是优化(如果必要)留给读者作为练习,就像填充结果一样(您已经有了一个函数)。在

相关问题 更多 >