Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/259.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 文本哈希技巧在Python和C中产生不同的结果#_C#_Python_Nlp - Fatal编程技术网

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

C# 文本哈希技巧在Python和C中产生不同的结果#,c#,python,nlp,C#,Python,Nlp,我试图将经过培训的模型移动到生产环境中,但在尝试复制C#中Keras hashing_trick()函数的行为时遇到了一个问题。当我对句子进行编码时,我的输出在C#中与在python中不同: Text:“信息-配置处理已完成。” Python:[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,0,0,0,0,4

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

Text:“信息-配置处理已完成。”

Python:[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,0,0,0,0,433,426,425,461,336,146,52]

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

我所尝试的:

  • 更改C#中文本字节的编码以匹配python字符串。encode()函数默认值(UTF8)
  • 将字母的大小写更改为小写和大写
  • 尝试使用Convert.ToUInt32而不是BitConverter(导致溢出错误)
  • 我的代码(如下)是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();
            }
        }
    
    public uint[]HashingTrick(字符串数据)
    {
    const int VOCAB_SIZE=534;//通过模型的python调试确定
    var filters=“!\$%&()*+,-./:;?@[\]^{\\}~\t\n”.ToCharArray().ToList();
    filters.ForEach(x=>
    {
    数据=数据。替换(x,'\0');
    });
    string[]parts=data.Split(“”);
    var encoded=新列表();
    parts.ToList().ForEach(x=>
    {
    使用(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);
    编码。添加(val%(VOCAB_大小-1)+1);
    }
    });
    返回PadSequence(编码,30);
    }
    专用单元[]焊盘顺序(列表序号,内部最大值)
    {
    如果(序号<最大值)
    {
    while(seq.CountmaxLen)
    {
    返回seq.GetRange(seq.Count-maxLen-1,maxLen.ToArray();
    }
    其他的
    {
    返回seq.ToArray();
    }
    }
    
    可以找到散列技巧的keras实现


    如果有帮助,我将使用ASP.NET Web API作为解决方案类型

    您的代码最大的问题是,它无法解释Python的
    int
    是一个任意精度的整数,而C#的
    uint
    只有32位。这意味着Python正在计算散列中所有128位的模,而C#不是(而且
    BitConverter.ToUInt32
    在任何情况下都是错误的,因为endianness是错误的)。另一个让您感到困惑的问题是,
    \0
    不会在C#中终止字符串,并且
    \0
    不能只添加到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();
    }
    
    样本使用:

    const int vocabSize = 534;
    Console.WriteLine(String.Join(" ",
        hashingTrick(
            text: "Information - The configuration processing is completed.",
            n: vocabSize,
            filters: "!#$%&()*+,-./:;<=>?@[\\]^_`{|}~\t\n",
            lower: true,
            split: " "
        ).Select(i => i.ToString())
    ));
    

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

    我没有解决试图与C#抗争以获得正确的哈希值的问题,而是采取了不同的方法来解决这个问题我决定使用@Jeron Mostert的哈希函数实现对数据集进行预哈希,然后再将其输入模型


    这个解决方案更易于实现,最终的效果与原始文本哈希一样好。给像我这样尝试进行跨语言哈希的人的建议是:不要这样做,这是一个非常头痛的问题!使用一种语言对文本数据进行哈希,并找到一种方法来创建包含所有所需信息的有效数据集

    感谢您提供的示例!似乎此代码适用于较小的句子(如问题中的句子),但适用于更详细的大型句子(假设这些句子可以超过100个单词)输出不正确。这是因为我有一个更大的字符串,因此需要散列更多的位吗?我不知道幻数
    534
    从哪里来——这是我调查的第一行。第二是看看哪些数字是正确的——在上面的代码中,每个整数对应一个散列字,所以如果存在差异,这是因为字符串的分割方式不同,或者结果的收集方式不同。我没有仔细调试Python代码(例如,尝试“配置”--Python是生成三个数字还是只生成一个数字?)另一方面,根据应用程序的不同,您可能希望了解直接运行Python代码的方法,而不是先将代码转换为C(您可以在同一应用程序中使用C提供API端点,并调用Python代码)。重新设计控制盘从来都不是一个好主意,尤其是如果当前控制盘功能完善的话。神奇的数字534来自于我正在使用的数据集中不同的总字数。这个数字用于创建哈希以及在Keras模型的嵌入层中。我试着使用IronPython,但没有使用hashlib库IronPython不支持Keras使用的y,这是因为hashlib是IronP不支持的C扩展
    217 142 262 113 319 413