I am using Accord.NET to create and save a StepwiseLogisticRegressionModel. When I try to serialize and save the model, I am getting the following error:
Type 'System.Threading.CancellationToken' in Assembly 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' is not marked as serializable.
Saving other models such as NaiveBayes seems to work fine.
Here is the code that I have tried:
StepwiseLogisticRegressionAnalysis model;
string file = Path.Combine(path, filename);
Serializer.Save(obj: model, path: file);
and
StepwiseLogisticRegressionAnalysis model;
string file = Path.Combine(path, filename);
using(FileStream stream = new FileStream(filename, FileMode.Create))
{
var binaryFormatter = new BinaryFormatter();
binaryFormatter.Serialize(stream, best);
}
How do I resolve this?
Edit: Here is a working example:
double[][] inputs =
{
// Age Smoking
new double[] { 55, 0 }, // 1
new double[] { 28, 0 }, // 2
new double[] { 65, 1 }, // 3
new double[] { 46, 0 }, // 4
new double[] { 86, 1 }, // 5
new double[] { 56, 1 }, // 6
new double[] { 85, 0 }, // 7
new double[] { 33, 0 }, // 8
new double[] { 21, 1 }, // 9
new double[] { 42, 1 }, // 10
new double[] { 33, 0 }, // 11
new double[] { 20, 1 }, // 12
new double[] { 43, 1 }, // 13
new double[] { 31, 1 }, // 14
new double[] { 22, 1 }, // 15
new double[] { 43, 1 }, // 16
new double[] { 46, 0 }, // 17
new double[] { 86, 1 }, // 18
new double[] { 56, 1 }, // 19
new double[] { 55, 0 }, // 20
};
double[] output =
{
0, 0, 0, 1, 1, 1, 0, 0, 0, 1,
0, 1, 1, 1, 1, 1, 0, 1, 1, 0
};
var regression = new StepwiseLogisticRegressionAnalysis(inputs, output,
new[] { "Age", "Smoking" }, "Cancer");
regression.Learn(inputs, output);
var path = $#"C:\";
var filename = "StepWiseRegressionModel.accord";
string file = Path.Combine(path, filename);
Serializer.Save(regression, file);
It looks like there's a private field somewhere in StepwiseLogisticRegressionAnalysis (or a subobject) that contains a CancellationToken, which can't be serialized.
You should try serializing the output model of the analysis (see the regression.Current.Regression property).
Just keep in mind that binary serialization of an object is fairly fragile, unless it's specifically supported. The deserialization environment has to be the exact same as the serialization (same library versions, C# versions, OS version, etc). Serializing the data, then reconstructing the object from it would be better if possible.
Related
I've got a jagged array,
int[][] array = new int[][] {
new int[] { 120, 120 },
new int[] { 135, 120 },
new int[] { 150, 120 },
new int[] { 165, 120 },
new int[] { 180, 120 }
};
I'd like to add new element in it **at the top/beginning ** like:
new int[] { 105, 120 },
And also, how to remove last element from it?
Is there a way I can achieve what I want?
You're going to want Array.Copy:
Array.Copy(array, 0, array, 1, array.Length - 1);
That will leave your array looking like:
int[][] array = new int[][] {
new int[] { 120, 120 },
new int[] { 120, 120 }
new int[] { 135, 120 },
new int[] { 150, 120 },
new int[] { 165, 120 },
};
That is, we've duplicated the first element, and overwritten the last. We can then assign the first element:
array[0] = new int[] { 105, 120 };
You might prefer to use a List<int[]>:
List<int[]> list = new List<int[]>()
{
new int[] { 120, 120 },
new int[] { 135, 120 },
new int[] { 150, 120 },
new int[] { 165, 120 },
new int[] { 180, 120 }
};
Then you can insert a new element at the beginning with:
list.Insert(0, new int[] { 105, 120 });
And remove the last element with:
list.RemoveAt(list.Length - 1);
A Queue<int[]> might be better still, as adding new items to the front will be cheaper.
In the code below, I am confused about why the line int[,][] jaggedArr = new int [ 2, 3 ] [];
requires to be counted normally, and not in elements like coders would practice.
I initially input it as int[,][] jaggedArr = new int [ 1, 2 ] [];, but wouldnt work.
Can someone please explain why this is so?
class JaggedArrays
{
static void Main (string[] args)
{
int[,][] jaggedArr = new int[2, 3][];
jaggedArr[0, 0] = new int[] { 0, 1, 2, 3, 4 };
jaggedArr[0, 1] = new int[] { 5, 6, 7, 8 };
jaggedArr[0, 2] = new int[] { 9, 10, 11, 12, 13, 14};
jaggedArr[1, 0] = new int[] { 15, 16, 17, 18, 19 };
jaggedArr[1, 1] = new int[] { 20, 21, 22, 23, 24 };
jaggedArr[1, 2] = new int[] { 25, 26, 27 };
Console.WriteLine(jaggedArr[0, 2][2]);
Console.WriteLine(jaggedArr.Length);
Console.ReadLine();
}
}
I wonder if it is possible to implement a general Julia\Matlab alike View function in C# that would work for arrays of any dimensions (eg [,,] and [,,,]) as they do it in array slicer\mover view. So I wonder if there is a library that provides similar functionality for CSharp multidimentional arrays or how to implement it in C#?
The solution is twofold:
Use a wrapper class that holds a reference to the master array
Use the Array base class to make it polymorphic
Wrapper
class View<T>
{
private readonly Array array;
private readonly int dim;
private readonly int slice;
public View(Array array, int dim, int slice)
{
this.array = array;
this.dim = dim;
this.slice = slice;
}
public T this[params int[] indexes]
{
get { return (T)array.GetValue(BaseIndexesFor(indexes)); }
set { array.SetValue(value, BaseIndexesFor(indexes)); }
}
private int[] BaseIndexesFor(int[] indexes)
{
if (indexes.Length != array.Rank - 1) throw new ArgumentException("indexes");
int i_index = 0;
int[] baseIndexes = new int[array.Rank];
for (int i = 0; i < baseIndexes.Length; i++)
{
baseIndexes[i] = (i == dim) ? slice : indexes[i_index++];
}
return baseIndexes;
}
}
2D example
var A = new int[,]
{
{ 1, 2, 3 },
{ 4, 5, 6 },
{ 7, 8, 9 }
};
/* View(Array array, int dim, int slice)
*
* For 2 dimensional array:
* dim=0 -> rows
* dim=1 -> columns
*/
// From second dimension slice index 1
// Or simply, take column with index 1
var B = new View<int>(A, 1, 1);
B[2] = 0;
Console.WriteLine(A[2, 1]); // 0
3D examples
var C = new int[,,]
{
{
{ 1, 2, 3 },
{ 4, 5, 6 },
{ 7, 8, 9 }
},
{
{ 11, 12, 13 },
{ 14, 15, 16 },
{ 17, 18, 19 }
},
{
{ 21, 22, 23 },
{ 24, 25, 26 },
{ 27, 28, 29 }
}
};
/* From first dimension slice index 2
* { 21, 22, 23 },
* { 24, 25, 26 },
* { 27, 28, 29 }
*/
var D = new View<int>(C, 0, 2);
D[1, 1] = 0;
Console.WriteLine(C[2, 1, 1]); // 0
/* From third dimension slice index 0
* { 1, 4, 7 },
* { 11, 14, 17 },
* { 21, 24, 27 }
*/
var E = new View<int>(C, 2, 0);
E[2, 0] = 0;
Console.WriteLine(C[2, 0, 0]); // 0
I have a 2D array as follows:
long[,] arr = new long[4, 4] {{ 5, 0, 0, 0 },
{ 8, 1, 1, 1 },
{ 0, 3, 0, 6 },
{ 1, 1, 1, 1 }};
How I can display distinct values form this array?
You can use Enumerable.Distinct method:
var uniqueValues = arr.Cast<long>().Distinct();
If I have 100 lists (eg x1 to x100), is there a better way of expressing the final line of code?
var x1 = new List<int>() { 75 };
var x2 = new List<int>() { 95, 64 };
var x3 = new List<int>() { 17, 47, 82 };
var x4 = new List<int>() { 18, 35, 87, 10 };
var x5 = new List<int>() { 20, 04, 82, 47, 65 };
var x6 = new List<int>() { 19, 01, 23, 75, 03, 34 };
var x7 = new List<int>() { 88, 02, 77, 73, 07, 63, 67 };
//etc..
var listOfListOfInts = new List<List<int>>() { x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15 };
possibly a Dictionary and a for loop to reference all the x1..100.
As long as x1 etc. aren't referenced elsewhere, then write:
var listOfListOfInts = new List<List<int>>()
{
new List<int>() { 75 },
new List<int>() { 95, 64 },
//etc.
};
In fact you shouldn't need to reference the individual variables elsewhere since listOfListOfInts[0] is just as good as x1 for example.
Do you really need these to be of type List<T>? It looks like you're setting up preinitialized data. If you're never going to change the length of any of these "lists", you could use arrays instead; the syntax is more compact:
var listOfListOfInts = new[] {
new[] { 75 },
new[] { 95, 64 },
new[] { 17, 47, 82 },
new[] { 18, 35, 87, 10 },
new[] { 20, 04, 82, 47, 65 },
new[] { 19, 01, 23, 75, 03, 34 },
new[] { 88, 02, 77, 73, 07, 63, 67 },
// ...
};
Perhaps i'm over complicating things but you could do something like
public interface IClass1
{
IList<IList<int>> ListList { get; set; }
void AddList(List<int> nList);
}
public class Class1 : IClass1
{
public IList<IList<int>> ListList { get; set; }
public void AddList(List<int> nList)
{
ListList.Add(nList);
}
}
and then use it like:
public class Create1
{
public Create1()
{
IClass1 iClass1 = new Class1();
iClass1.AddList(new List<int>() { 75 });
}
}