Numpy.NET 获取值

Numpy.NET Getting Values

我正在尝试将 F. Chollet 制作的 Keras 笔记本“转换”为 C#/.NET 应用程序。您可以找到它们 here。我现在专门从事“3.5 - 电影评论”。

问题是,我无法将 NDarray 转换为 C# 数组以使用这些值。我尝试了 this 方法(在 README - Performance Considerations 部分),但我得到随机值或 Python 运行时错误。

using Keras.Datasets;
using Numpy;
using System;
using System.Collections.Generic;
using System.Windows.Forms;

namespace ClassifyingMovieReviews
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        // Variables
        NDarray train_data, train_labels, test_data, test_labels;
        NDarray x_train, y_train, x_test, y_test;

        public NDarray VectorizeSequences(NDarray sequence, int dimension = 10000)
        {
            NDarray output = np.zeros((sequence.size, dimension));
            int[] value = { 1 };
            
            // this works to extract the first line (as an NDarray!)
            NDarray line0 = sequence[0];
            
            // nothing works (of those three)
            var raw_data_1 = sequence.GetData<int>();
            Console.WriteLine("raw_data_1: " + raw_data_1);

            var raw_data_2 = sequence.GetData<float>();
            Console.WriteLine("raw_data_2: " + raw_data_2);

            var raw_data_3 = sequence.GetData<double>();
            Console.WriteLine("raw_data_3: " + raw_data_3);
            
            return output;
        }

        private void ReadData()
        {
            // parameters
            int top_words = 10000;

            // the data, split between train and test sets
            ((train_data, train_labels), (test_data, test_labels)) = IMDB.LoadData(num_words: top_words);

            // Our vectorized training & test data
            x_train = VectorizeSequences(train_data);
            x_test = VectorizeSequences(test_data);
        }
    }
}

此外,我的 train_data 和 test_data 似乎是正确的,它们看起来像这样:

train_data = {
    [
        list([1, 14, 22, ..., 178, 32])
        list([1, 194, 1153, ..., 95])
        list([1, 14, 47, 8, ..., 2])
        ...
        list([1, 17, 6, ..., 131, 9])
    ]
}
Numpy.NDarray

编辑:我查看了 Github 源代码以找到解决方案

  • GetData<>()

此方法只接受少量类型。我对它们进行了全部测试,但没有任何效果。
我怀疑它不能正常工作,因为我没有多维 NDarray,而是 Python.Runtime 'list' 个对象的 NDarray。

using Keras.Datasets;
using Numpy;

// Variables
NDarray train_data, train_labels, test_data, test_labels;
NDarray x_train, y_train, x_test, y_test;
int top_words = 10000;

// the data, split between train and test sets
((train_data, train_labels), (test_data, test_labels)) = IMDB.LoadData(
        num_words: top_words
);

// GetData testing
byte[] byteToCsharp = train_data.GetData<byte>();
short[] shortToCsharp = train_data.GetData<short>();
int[] intToCsharp = train_data.GetData<int>();
long[] longToCsharp = train_data.GetData<long>();
float[] floatToCsharp = train_data.GetData<float>();
double[] doubleToCsharp = train_data.GetData<double>();
bool[] boolToCsharp = train_data.GetData<bool>();

可以找到 GetData 函数签名 here。或者,转到 SciSharp/Numpy.NET 存储库并在搜索栏中搜索“GetData”。

  • PadSequences()

这是在 C# 中操作 IMDB 数据集并对序列进行矢量化的答案。请注意,它没有解决我将从 IMDB.LoadData() 获得的 NDarray 转换为 C# 本机数组的问题。

using Keras.Datasets;
using Keras.PreProcessing.sequence;
using Numpy;

// Variables
NDarray train_data, train_labels, test_data, test_labels;
NDarray x_train, y_train, x_test, y_test;
int top_words = 10000;

((x_train, y_train), (x_test, y_test)) = IMDB.LoadData(
        num_words: top_words
);

int max_words = 500;
x_train = SequenceUtil.PadSequences(x_train, maxlen: max_words);
x_test = SequenceUtil.PadSequences(x_test, maxlen: max_words);

相反,如果我对函数的理解正确,它会直接调用 Python 中的函数。您可以找到它 here,或在 SciSharp/Keras.NET 存储库的搜索栏中搜索“PadSequences”。

总结

NDarray 上的通用 GetData<T>() 方法您想要的

您只需要:

  • 使用正确的数据类型
  • 注意 NDarray 的形状

您可以获得例外情况,例如:

  • System.InvalidOperationException
  • Python.Runtime.PythonException

如果你弄错了这两位中的任何一位,例如泛型的错误类型或试图从包含本身不是数组的数据的 NDarray(或其维度或切片)中获取数组。您不需要编写自己的代码 ParseManuallyIntoArrayOfInts

例子

using Numpy;

    
var nDimArray = np.array(new int[] { 1, 2, 3, 4 }).reshape(2, 2);    
int[] allElementsFlattened = nDimArray.GetData<int>();
    
int[] arrayFromDim0 = nDimArray[0].GetData<int>();
int[] arrayFromDim1 = nDimArray[1].GetData<int>();

而尝试获取 错误类型的数据:

var x = nDimArray[1].GetData<object>() 
threw an exception of type 'System.InvalidOperationException'

而试图获取 与形状不匹配的数据:

var x = nDimArray[0][0].GetData<int>() 
threw an exception of type 'Python.Runtime.PythonException'

字符串化 C# 数组

你的 Console.WriteLine() 不会给你我所期望的 want/expect。您需要做一点工作来转向,例如将 int[] 转换为字符串(在类型的默认输出之上)。

要获得有用的字符串表示,请尝试这样的操作:

    Console.WriteLine($"[{String.Join(", ", nDimArray.GetData<int>()) }]");

哪个会给你例如:

"[1, 2, 3, 4]"

建议使用断点和监视来查看代码不同步骤中的 NDarray 对象中的内容。

简单的辅助函数

或者,如果您有很多 NDarray 使用推理代码来处理,您还可以创建一个小辅助函数来将核心细节写入调试/控制台,例如:

public static void DisplayNDarray(NDarray nDarray, string name = "")
{
    Debug.WriteLine($">> DisplayDetails {name}:");
    Debug.WriteLine($"size {nDarray.size} shape {nDarray.shape} dims {nDarray.ndim}");
    Debug.WriteLine($"mean {nDarray.mean()} std {nDarray.std()} min {nDarray.min()} max {nDarray.max()}");
}

额外的辅助功能

而对于 ,当您知道数据的基础类型 时,您可以使用另一个简单的助手将数据可视化为字符串

public static void DisplayNDarrayData<TElementType>(NDarray nDarray)
{
    Debug.WriteLine($"[{String.Join(", ", nDarray.GetData<TElementType>())}]");
}

被称为:

DisplayNDarrayData<int>(nDimArray);