为什么;conv1d";在C代码、python和pytorch中是不同的

为什么;conv1d";在C代码、python和pytorch中是不同的,python,c,conv-neural-network,pytorch,Python,C,Conv Neural Network,Pytorch,我想用C代码重现pytorch的“Conv1D”结果 我尝试使用三种方法(C代码、Python、Pytork)实现“Conv1D”,但结果不同。只有七个小数位数是合理的。假设结构中存在多层conv1d,分数位数精度将逐渐降低 根据大家的建议,我尝试将输入数据的C代码类型更改为double,但结果仍然不正确。 我做错什么了吗 例如:   Pytorch的输出:0.2380688339471817017   Python的输出:0.2380688637495040894   C代码输出(浮点):0.

我想用C代码重现pytorch的“Conv1D”结果

我尝试使用三种方法(C代码、Python、Pytork)实现“Conv1D”,但结果不同。只有七个小数位数是合理的。假设结构中存在多层conv1d,分数位数精度将逐渐降低

根据大家的建议,我尝试将输入数据的C代码类型更改为
double
,但结果仍然不正确。 我做错什么了吗

例如:

  Pytorch的输出:0.2380688339471817017

  Python的输出:0.2380688637495040894

  C代码输出(浮点):0.2380688637

  C代码的输出(双精度):0.238068885344539680

这是我当前的实现

  • 输入:

      输入尺寸=80,输出尺寸=128,内核大小=5

      Pytorch:Conv1D_input.npy、Conv1D_weight.npy

      Python:Conv1D_input.npy、Conv1D_weight.npy(与Pytorch相同)

      C代码:Conv1D_input.txt、Conv1D_weight.txt(从Pytorch、IEEE 754单精度转换)

      Pytorch

    import torch
    import numpy as np
    from torch import nn
    from torch.autograd import Variable
    import torch.nn.functional as F
    import argparse
    import sys
    import io
    import time
    import os
    
    class RNN(nn.Module):
        def __init__(self, input_size, hidden_size):
            super(RNN, self).__init__()
            self.input_size = input_size
            self.hidden_size = hidden_size
    
            self.c1 = nn.Conv1d(input_size, hidden_size, kernel_size = 5, bias=False)
            self.c1.weight = torch.nn.Parameter(torch.Tensor(np.load("CONV1D_WEIGHT.npy")))    
    
        def forward(self, inputs):
            c = self.c1(inputs)
            return c
    
    input_size = 80
    hidden_size = 128
    kernel_size = 5
    
    rnn = RNN(input_size, hidden_size)
    
    inputs = torch.nn.Parameter(torch.Tensor(np.load("CONV1D_IN.npy")))
    print("inputs", inputs)
    outputs = rnn(inputs)
    sub_np456 = outputs[0].cpu().detach().numpy()
    np.savetxt("Pytorch_CONV1D_OUTPUT.txt", sub_np456)
    print('outputs', outputs)
    
      Python

    import struct
    import numpy as np
    
    if __name__ == "__main__":
        row = 80
        col = 327
        count = 0
        res_out_dim = 128
        in_dim = 80
        kernel_size = 5
        filter = np.zeros((80, 5), dtype = np.float32)
        featureMaps = np.zeros((128, 323), dtype = np.float32)
    
        spectrum = np.load("CONV1D_INPUT.npy")
        weight = np.load("CONV1D_WEIGHT.npy")
    
        spectrum_2d = spectrum.reshape(80, 327)
    
        for i in range(res_out_dim):
            for j in range(in_dim): 
                for k in range(kernel_size):
                    filter[j][k] = weight[i][j][k]
    
            while count < (col-kernel_size+1):
                for j in range(in_dim):
                    for k in range(count, kernel_size+count):
                        featureMaps[i][count] = featureMaps[i][count] + spectrum_2d[j][k]*filter[j][k-count]
                count = count + 1
            count = 0
    
        np.savetxt("Python_CONV1D_OUTPUT.txt", featureMaps)
    
    导入结构
    将numpy作为np导入
    如果名称=“\uuuuu main\uuuuuuuu”:
    行=80
    col=327
    计数=0
    res_out_dim=128
    英寸=80
    内核大小=5
    filter=np.zero((80,5),dtype=np.float32)
    featureMaps=np.zero((128323),dtype=np.float32)
    频谱=np.负载(“CONV1D\u INPUT.npy”)
    重量=np.荷载(“CONV1D\u重量.npy”)
    频谱_2d=频谱重塑(80327)
    对于i范围内(分辨率范围外):
    对于范围内的j(单位尺寸):
    对于范围内的k(内核大小):
    过滤器[j][k]=重量[i][j][k]
    当计数<(列内核大小+1)时:
    对于范围内的j(单位尺寸):
    对于范围内的k(计数、内核大小+计数):
    featureMaps[i][count]=featureMaps[i][count]+频谱图2d[j][k]*滤波器[j][k-count]
    计数=计数+1
    计数=0
    np.savetxt(“Python\u CONV1D\u OUTPUT.txt”,featureMaps)
    
      C代码(浮点)

    #包括
    #包括
    #包括
    #包括
    const char CONV1D_WEIGHT[]=“CONV1D_WEIGHT.txt”;
    const char CONV1D_INPUT[]=“CONV1D_INPUT.txt”;
    void参数free(浮点**矩阵,整数行)
    {
    int i=0;
    
    对于(i=0;i而言,浮点数是不精确的(通过设计)。根据执行的顺序运算,结果可能会有所不同。更糟糕的是,一些公式是直接数值不稳定的,而另一个用于相同分析表达式的公式可能是稳定的


    编译器经常将语句重新设置范围作为优化措施。卷积运算是一种包含大量运算和循环的运算。因此,除非您直接比较执行的字节码,否则这种推测是毫无意义的。

    请不要显示文本图像(至少作为链接,问题应该是自包含的),将文本复制粘贴到问题中作为文本。另外,请花一些时间阅读。对不起,我的不好。我会修复它。对于这样高的精度,您应该使用
    double
    而不是
    float
    您也可以使用
    long double
    。不要忘记更改
    scanf
    printf
    format说明符当前的输入和权重数据格式是IEEE 754(单精度)。在我看来,使用浮点存储似乎相当合理。@Haritts-对于Python,浮点值的默认精度是53位(对应于64位浮点).在C语言中,a
    float
    通常是32位的值,对于64位,您通常需要双精度
    double
    谢谢您的建议,您的意思是,如果pytorch和C代码的结果相同,我需要比较汇编语言?
    #include<stdio.h>
    #include<stdlib.h>
    #include<math.h>
    #include<time.h>
    
    const char CONV1D_WEIGHT[] = "CONV1D_WEIGHT.txt";
    const char CONV1D_INPUT[] = "CONV1D_INPUT.txt";
    
    void parameterFree(float **matrix, int row)
    {
        int i = 0;
        for(i=0; i<row; i++)
            free(matrix[i]);
        free(matrix);
    }
    
    float** createMatrix_2D(int row, int col)
    {
        int i = 0;
        float **matrix = NULL;
        matrix = (float**)malloc(sizeof(float*) * row);
        if(matrix == NULL)
            printf("Matrix2D malloc failed\n");
        for(i=0; i<row; i++)
        {
            matrix[i] = (float*)malloc(sizeof(float) * col);
            if(matrix[i] == NULL)  
                printf("Matrix2D malloc failed\n");
        }
    
        return matrix;
    }
    
    float** conv_1D(const char weightFile[], float **source, int *row, int *col, int in_dim, int res_out_dim, int kernel_size)
    {   
        float **filter = createMatrix_2D(in_dim, kernel_size);   
        float **featureMaps = createMatrix_2D(res_out_dim, *col-kernel_size+1);
        int i = 0, j = 0, k = 0, count = 0;
        char str[10];
        float data = 0.0;
        FILE *fp = fopen(weightFile, "r");   
        if(fp == NULL)
            printf("Resnet file open failed\n");
        else
        {                  
            /*initial featureMaps*/
            for(i=0; i<res_out_dim; i++)
            {
                for(j=0; j<*col-kernel_size+1; j++)
                {
                    featureMaps[i][j] = 0.0;
                }
            }
    
            /*next filter*/        
            for(i=0; i<res_out_dim; i++) 
            {
                /*read filter*/
                for(j=0; j<in_dim; j++) 
                {
                    for(k=0; k<kernel_size; k++) 
                    {
                        fscanf(fp, "%s", str);
                        sscanf(str, "%x", &data);
                        filter[j][k] = data;                                        
                    }               
                }
    
                /* (part of source * filter) */            
                while(count < *col-kernel_size+1)
                {                
                    for(j=0; j<in_dim; j++)
                    {                                       
                        for(k=count; k<kernel_size+count; k++)
                        {
                            featureMaps[i][count] += source[j][k]*filter[j][k-count];
                        }
                    }               
                    count++;               
                }
                count = 0;          
            }
            fclose(fp);
        }
        parameterFree(source, *row);
        parameterFree(filter, in_dim);
        *row = res_out_dim;
        *col = *col-kernel_size+1;       
    
        return featureMaps;  
    }
    
    int main()
    {
        int row = 80;
        int col = 327;
        int in_dim = 80;
        int res_out_dim = 128;
        int kernel_size = 5;
        int i, j;
        float data;
        char str[10];
    
        float **input = createMatrix_2D(row, col);
        FILE *fp = fopen(CONV1D_INPUT, "r");
        FILE *fp2 = fopen("C code_CONV1D_OUTPUT.txt", "w");
        if(fp == NULL)
            printf("File open failed\n");
        else
        {
            for(i=0; i<row; i++) 
            {
                for(j=0; j<col; j++) 
                {
                    fscanf(fp, "%s", str);
                    sscanf(str, "%x", &data);
                    input[i][j] = data;                                        
                }               
            }
        }
    
        float **CONV1D_ANS = conv_1D(CONV1D_WEIGHT, input, &row, &col, in_dim, res_out_dim, kernel_size);
    
        for(i=0; i<row; i++) 
        {
            for(j=0; j<col; j++) 
            {
                fprintf(fp2, "[%.12f] ", CONV1D_ANS[i][j]);
            }
            fprintf(fp2, "\n");
        }
    
        return 0;
    }
    
    #include<stdio.h>
    #include<stdlib.h>
    #include<math.h>
    #include<time.h>
    
    const char CONV1D_WEIGHT[] = "CONV1D_WEIGHT.txt";
    const char CONV1D_INPUT[] = "CONV1D_INPUT.txt";
    
    void parameterFree(double **matrix, int row)
    {
        int i = 0;
        for(i=0; i<row; i++)
            free(matrix[i]);
        free(matrix);
    }
    
    double** createMatrix_2D(int row, int col)
    {
        int i = 0;
        double **matrix = NULL;
        matrix = (double**)malloc(sizeof(double*) * row);
        if(matrix == NULL)
            printf("Matrix2D malloc failed\n");
        for(i=0; i<row; i++)
        {
            matrix[i] = (double*)malloc(sizeof(double) * col);
            if(matrix[i] == NULL)  
                printf("Matrix2D malloc failed\n");
        }
    
        return matrix;
    }
    
    double** conv_1D(const char weightFile[], double **source, int *row, int *col, int in_dim, int res_out_dim, int kernel_size)
    {   
        double **filter = createMatrix_2D(in_dim, kernel_size);   
        double **featureMaps = createMatrix_2D(res_out_dim, *col-kernel_size+1);
        int i = 0, j = 0, k = 0, count = 0;
        char str[10];
        float data = 0.0;
        FILE *fp = fopen(weightFile, "r");   
        if(fp == NULL)
            printf("Resnet file open failed\n");
        else
        {                  
            /*initial featureMaps*/
            for(i=0; i<res_out_dim; i++)
            {
                for(j=0; j<*col-kernel_size+1; j++)
                {
                    featureMaps[i][j] = 0.0;
                }
            }
    
            /*next filter*/        
            for(i=0; i<res_out_dim; i++) 
            {
                /*read filter*/
                for(j=0; j<in_dim; j++) 
                {
                    for(k=0; k<kernel_size; k++) 
                    {
                        fscanf(fp, "%s", str);
                        sscanf(str, "%x", &data);
                        filter[j][k] = (double)data;                                        
                    }               
                }
    
                /* (part of source * filter) */            
                while(count < *col-kernel_size+1)
                {                
                    for(j=0; j<in_dim; j++)
                    {                                       
                        for(k=count; k<kernel_size+count; k++)
                        {
                            featureMaps[i][count] += source[j][k]*filter[j][k-count];
                        }
                    }               
                    count++;               
                }
                count = 0;          
            }
            fclose(fp);
        }
        parameterFree(source, *row);
        parameterFree(filter, in_dim);
        *row = res_out_dim;
        *col = *col-kernel_size+1;       
    
        return featureMaps;  
    }
    
    int main()
    {
        int row = 80;
        int col = 327;
        int in_dim = 80;
        int res_out_dim = 128;
        int kernel_size = 5;
        int i, j;
        float data;
        char str[10];
    
        double **input = createMatrix_2D(row, col);
        FILE *fp = fopen(CONV1D_INPUT, "r");
        FILE *fp2 = fopen("C code_CONV1D_OUTPUT.txt", "w");
        if(fp == NULL)
            printf("File open failed\n");
        else
        {
            for(i=0; i<row; i++) 
            {
                for(j=0; j<col; j++) 
                {
                    fscanf(fp, "%s", str);
                    sscanf(str, "%x", &data);
                    input[i][j] = (double)data;                                        
                }               
            }
        }
    
        double **CONV1D_ANS = conv_1D(CONV1D_WEIGHT, input, &row, &col, in_dim, res_out_dim, kernel_size);
    
        for(i=0; i<row; i++) 
        {
            for(j=0; j<col; j++) 
            {
                fprintf(fp2, "[%.18f] ", CONV1D_ANS[i][j]);
            }
            fprintf(fp2, "\n");
        }
    
        return 0;
    }