I've run into a stall trying to put together some code to average out 10x10 subarrays of a 2D multidimensional array.
Given a multidimensional array
var myArray = new byte[100, 100];
How should I go about creating 100 subarrays of 100 bytes (10x10) each.
Here are some examples of the value indexes the subarrays from the multidimensional would contain.
[x1,y1,x2,y2]
Subarray1[0,0][9,9]
Subarray2[10,10][19,19]
Subarray3[20,20][29,29]
Given these subarrays, I would then need to average the subarray values to create a byte[10,10] from the original byte[100,100].
I realize this is not unbelievably difficult, but after spending 4 days debugging very low-level code and now getting stuck on this would appreciate some fresh eyes.
Use this as a reference. I used ints just for ease of use. Code is untested. but the idea is there.
var rowSize = 100;
var colSize = 100;
var arr = new int[rowSize, colSize];
var r = new Random();
for (int i = 0; i < rowSize; i++)
for (int j = 0; j < colSize; j++)
arr[i, j] = r.Next(20);
for (var subcol = 0; subcol < colSize / 10; subcol++)
{
for (var subrow = 0; subrow < colSize/10; subrow++)
{
var startX = subcol*10;
var startY = subrow*10;
var avg = 0;
for (var x=0; x<10; x++)
for (var y = 0; y < 10; y++)
avg += arr[startX + x, startY + y];
avg /= 10*10;
Console.WriteLine(avg);
}
}
It looks like you're new to SO. Next time try to post your attempt at the problem; it's better to fix your code.
The only challenge is figuring out the function, that given the subarray index we're trying to populate, would give you the correct row and column indexes in your original 100x100 array; the rest would just be a matter of copying the values:
// psuedocode
// given a subarrayIndex of 0 to 99, these will calculate the correct indices
rowIndexIn100x100Array = (subarrayIndex / 10) * 10 + subArrayRowIndexToPopulate;
colIndexIn100x100Array = (subarrayIndex % 10) * 10 + subArrayColIndexToPopulate;
I'll leave it as an exercise to you to deduce why the above functions correctly calculate the indices.
With the above, we can easily map the values:
var subArrays = new List<byte[,]>();
for (int subarrayIndex = 0; subarrayIndex < 100; subarrayIndex++)
{
var subarray = new byte[10, 10];
for (int i = 0; i < 10; i++)
for (int j = 0; j < 10; j++)
{
int rowIndexIn100x100Array = (subarrayIndex / 10) * 10 + i;
int colIndexIn100x100Array = (subarrayIndex % 10) * 10 + j;
subarray[i, j] = originalArray[rowIndexIn100x100Array, colIndexIn100x100Array];
}
subArrays.Add(subarray);
}
Once we have the 10x10 arrays, calculating the average would be trivial using LINQ:
var averages = new byte[10, 10];
for (int i = 0; i < 10; i++)
for (int j = 0; j < 10; j++)
{
averages[i, j] = (byte)subArrays[(i * 10) + j].Cast<byte>().Average(b => b);
}
Fiddle.
Related
I've made a neural network in C# from scratch.
The problem is that when I try to train it for an XOR logic gate, it always converges to 0.5, instead of alternating between 0 and 1.
The neural network is made to work with a custumizable number of layers and nodes.
I've been over the theory countless of times, but I have no idea where the problem could be. I have excluded the bias in the backpropagation.
The backpropagation algorithm:
Neuralnetwork is constructed as follows:
nn.layerlist[x] = specific layer
nn.layerlist[x].network[y] = specific node
nn.layerlist[x].network[y].weight[z] = specific weight leading towards that node
public static NeuralNetwork Calculate(NeuralNetwork nn, List<double> Target, double LearningRate)
{
var OutputLayer = nn.LayerList.Count - 1;
var node = nn.LayerList[OutputLayer].Network[0];
List<List<double>> WeightList = new List<List<double>>();
List<double> Weights = new List<double>();
//Weightlist initialiseren
for (int i = 0; i < node.Weights.Count; i++)
Weights.Add(0);
// Door de laatste layer eerst gaan
for (int i = 0; i < Target.Count(); i++)
{
for (int j = 0; j < node.Weights.Count; j++)
{
var weight = nn.LayerList[OutputLayer].Network[i].Weights[j];
var outputcurrent = nn.LayerList[OutputLayer].Network[i].Value;
var OutputPrevious = nn.LayerList[OutputLayer - 1].Network[j].Value;
var Cost = (outputcurrent - Target[i]) * (outputcurrent * (1 - outputcurrent));
Weights[j] += Cost * weight;
weight = weight - (Cost * OutputPrevious * LearningRate);
nn.LayerList[OutputLayer].Network[i].Weights[j] = weight;
}
}
WeightList.Add(Weights);
int layercount = nn.LayerList.Count - 1;
//alle layers in reverse bijlangs gaan
for (int i = layercount; i > 0; i--)
{
var WeightsHidden = new List<double>();
for(int k = 0; k < 1000; k++) //TODO: Change this to something dynamic!
WeightsHidden.Add(0);
for (int j = 0; j < nn.LayerList[i].Network.Count; j++)
{
for (int k = 0; k < nn.LayerList[i].Network[j].Weights.Count; k++)
{
var weight = nn.LayerList[i].Network[j].Weights[k];
var outputcurrent = nn.LayerList[i].Network[j].Value;
var OutputPrevious = nn.LayerList[i - 1].Network[k].Value;
Console.WriteLine("Total Weights: {0}", WeightList[WeightList.Count - 1][k]);
var Cost = (outputcurrent * (1 - outputcurrent)) * WeightList[WeightList.Count - 1][k];
WeightsHidden[k] += Cost * weight;
weight = weight - (Cost * OutputPrevious * LearningRate);
nn.LayerList[i].Network[j].Weights[k] = weight;
}
}
WeightList.Add(WeightsHidden);
}
return nn;
}
}
The code is quite complex, but I have no idea how to format it in any other way.
I would like to neural network to put out the desired result like an XOR gate.
I am new in C# and I have a problem with for loops in lists.
I have a list with numbers (called alpha) which go from 0 to 7.
alpha0=1
alpha1=2
alpha2=3
...
alpha7=8
Now I want to create a matrix containing all these alphas in this way and then I want to transpose it:
I've tried to write the transposed one directly but it gives me error or better I am wrong with the syntax (see last string of my code). Could somebody help me?
I called startinglist my list with alphas.
List<List<double>> arr = new List<List<double>>();
for (int col = 0; col < 8; col++)
for (int row = 0; row < 7; row++)
arr[col, row].Add(startinglist[col]);
Try below code:
var size = 8;
var alpha = Enumerable.Range(1, size).ToArray();
var matrix = new int[size, size + 1];
for (int i = 0; i < size; i++)
{
// Assign values on the diagonal.
matrix[i, i] = alpha[i];
matrix[i, i + 1] = 1 - alpha[i];
}
Try this:
var size = 8;
int[] alpha = Enumerable.Range(1, size).ToArray();
int[][] C = new int[size - 1][];
for(int i = 0 ; i < size - 1; i++)
{
C[i] = new int[size];
C[i][i] = alpha[i];
C[i][i + 1] = 1 - alpha[i + 1];
}
Edit:
Since you have alpha already defined as a list, you may use this:
Edit2:
Changed int to double:
double[][] C = new double[alpha.Count - 1][];
for(int i = 0 ; i < alpha.Count - 1; i++)
{
C[i] = new double[alpha.Count];
C[i][i] = alpha[i];
C[i][i + 1] = 1 - alpha[i + 1];
}
Basically i'm trying to multiply each element of the first array with each element of the second array and then store it all at the end as a total. I'm pretty new to coding so just trying to learn and this one really has me stuck. This is the example of what it should eventually do.
ExampleArray1 = 5,6,7,8
ExampleArray2 = 2,3,4
(5*2)+(5*3)+(5*4) + (6*2)+(6*3)+(6*4) + (7*2)+(7*3)+(7*4) + (8*2)+(8*3)+(8*4) = 234
My code
int[] firstArray = { 5, 6, 7, 8 };
int[] secondArray = { 2, 3, 4 };
int[] thirdArray = new int[firstArray.Length * secondArray.Length];
for (int i = 0; i < firstArray.Length; i++)
for (int j = 0; j < secondArray.Length; j++)
{
thirdArray[i * firstArray.Length + j] = firstArray[i] * secondArray[j];
Console.WriteLine(thirdArray[i * firstArray.Length + j]);
}
You dont need a third array, you can just sum the results
var total = 0;
for (int i = 0; i < firstArray.Length; i++)
for (int j = 0; j < secondArray.Length; j++)
{
total += (firstArray[i] * secondArray[j]);
}
Console.WriteLine(total);
However you forgot to minus one form the length, in the third array index.
i.e to get the index you need i * (firstArray.Length - 1) + j
int[] thirdArray = new int[firstArray.Length * secondArray.Length];
for (int i = 0; i < firstArray.Length; i++)
for (int j = 0; j < secondArray.Length; j++)
{
thirdArray[i * (firstArray.Length - 1) + j] = firstArray[i] * secondArray[j];
}
Console.WriteLine(thirdArray.Sum());
You can apply some basic algebra to simplify this:
var total = 0;
var array1Total = 0;
var array2Total = 0;
for (int i = 0; i < firstArray.Length; i++)
{
array1Total += firstArray[i];
}
for (int j = 0; j < secondArray.Length; j++)
{
array2Total += secondArray[j];
}
total = array1Total * array2Total;
Console.WriteLine(total);
The reason is that if you expand (x0+x1+x2+x3...)*(y0+y1+y2+...) then you can see that you will multiply x0 by each of the y, then multiply x1 by each of the y, and so on. So you'll get each of the elements in the first brackets multiplied by each of the elements in the second brackets.
While this may not seem much different it will be considerably better for large arrays. if the length of your arrays are m and n then by the nested loops method you'll have m*n loop iterations. With the above technique you will have m+n. For small values this isn't a big deal. If you have arrays of thousands of items then the above will be significantly faster.
Of course, there is an even easier way to do the above:
var total = firstArray.Sum()*secondArray.Sum();
Really I'm trying to apply 3X3 Median Filtering by C# and depending on my understanding the concepts of Median Filtering I wrote the following code but when I'm running it the Form hangs. I think have some problem in the last nested for loop but i don't know where is the error or the wrong in applying the Median concepts!
public static Bitmap MedianFiltering(Bitmap bm)
{
List<int> termsList = new List<int>();
Bitmap res, temp;
Color c;
int counter = 0;
//Convert to Grayscale
for (int i = 0; i < bm.Width; i++)
{
for (int j = 0; j < bm.Height; j++)
{
c = bm.GetPixel(i, j);
byte gray = (byte)(.333 * c.R + .333 * c.G + .333 * c.B);
bm.SetPixel(i, j, Color.FromArgb(gray, gray, gray));
}
}
temp = bm;
//applying Median Filtering
for (int i = 0; i <= temp.Width - 3; i++)
for (int j = 0; j <= temp.Height - 3; j++)
{
for (int x = i; x <= i + 2; x++)
for (int y = j; y <= j + 2; y++)
{
c = temp.GetPixel(x, y);
termsList.Add(c.R);
counter++;
}
int[] terms = termsList.ToArray();
Array.Sort<int>(terms);
Array.Reverse(terms);
int color = terms[4];
temp.SetPixel(i + 1, j + 1, Color.FromArgb(color, color, color));
counter = 0;
}
res = temp;
return res;
}
Thanks.
You are not clearing the termsList after each pixel processing. This is causing the list to keep growing. Sorting and reversing the list will keep taking longer and longer times. This will also cause incorrect results since you only want to get the median of the 9 pixels related to the current pixel.
Simply clear the list like this:
...
int[] terms = termsList.ToArray();
termsList.Clear();
...
UPDATE:
I did more optimization for the code:
public static void MedianFiltering(Bitmap bm)
{
List<byte> termsList = new List<byte>();
byte[,] image = new byte[bm.Width,bm.Height];
//Convert to Grayscale
for (int i = 0; i < bm.Width; i++)
{
for (int j = 0; j < bm.Height; j++)
{
var c = bm.GetPixel(i, j);
byte gray = (byte)(.333 * c.R + .333 * c.G + .333 * c.B);
image[i, j] = gray;
}
}
//applying Median Filtering
for (int i = 0; i <= bm.Width - 3; i++)
for (int j = 0; j <= bm.Height - 3; j++)
{
for (int x = i; x <= i + 2; x++)
for (int y = j; y <= j + 2; y++)
{
termsList.Add(image[x, y]);
}
byte[] terms = termsList.ToArray();
termsList.Clear();
Array.Sort<byte>(terms);
Array.Reverse(terms);
byte color = terms[4];
bm.SetPixel(i + 1, j + 1, Color.FromArgb(color, color, color));
}
}
Please note that in your original method, you returned a Bitmap. I removed this.
Please note that temp = bm; does not create a copy of the Bitmap. It is just pointing the temp variable to the same object (that is pointed by bm). So in your original method, you returned the exact object that is passed in the method parameter. To use the new method pass the Bitmap and then the bitmap it self will be modified (this is also true for your method).
This enhanced performance 4 times on my machine.
What I did is mainly read the bitmap data into a byte array instead of using the Bitmap it self to read/write data multiple times.
If you need to further enhance the performance, take a look at this question.
static void Main(string[] args)
{
Random r = new Random();
int[,] x = new int[10,8];
int[] temp = new int[x.Length];
// two dimensional array and i want for three dimensional array
for(int i = 0; i < temp.Length; i++)
{
temp[i] = r.Next(10, 100);
for(int j = 0; j < i; j++)
{
if(temp[i] == temp[j])
{
i--;
break;
}
}
}
for(int i = 0, index = 0; i < x.GetLength(0); i++)
{
for(int j = 0; j < x.GetLength(1); j++)
{
x[i, j] = temp[index++]; //two dimensional array unique numbers
Console.Write(x[i, j] + " ");
}
}
// i want do it as for 3D and 4 D array unique numbers like that method what can i change or add?
It's pretty straight forward to do what you're doing for higher dimensions.
Here's my code for 3D:
var r = new Random();
int [,,] x = new int[10, 8, 8];
var count =
Enumerable
.Range(0, x.Rank)
.Select(y => x.GetLength(y))
.Aggregate((y, z) => y * z);
var values =
Enumerable
.Range(10, count)
.OrderBy(y => r.Next())
.ToArray();
var v = 0;
for (var i = x.GetLowerBound(0); i <= x.GetUpperBound(0); i++)
for (var j = x.GetLowerBound(1); j <= x.GetUpperBound(1); j++)
for (var k = x.GetLowerBound(2); k <= x.GetUpperBound(2); k++)
x[i, j, k] = values[v++];
To change it to 4D these lines change:
int [,,,] x = new int[10, 8, 8, 12];
// ...
var v = 0;
for (var i = x.GetLowerBound(0); i <= x.GetUpperBound(0); i++)
for (var j = x.GetLowerBound(1); j <= x.GetUpperBound(1); j++)
for (var k = x.GetLowerBound(2); k <= x.GetUpperBound(2); k++)
for (var l = x.GetLowerBound(3); l <= x.GetUpperBound(3); l++)
x[i, j, k, l] = values[v++];
Now, in this code I have explicitly called GetLowerBound as well as GetUpperBound as it is possible in .NET code to have a non-zero based array.
Also, rather than repeatedly re-try getting random numbers until you have unique numbers I simply generated a sequence of unique numbers and then randomly sorted them. That's a little different from your original code. You needed 80 (10 x 8) random values and you were choosing from values ranging from 10 to 99 inclusive. So you had some holes in your numbers.
Random r = new Random();
int[,,] x = new int[10, 8, 8];
int[] temp = new int[x.Length];
#region one dimensional array unique numbers.
for (int i = 0; i < temp.Length; i++)
{
temp[i] = r.Next(10, 650);
for (int j = 0; j < i; j++)
{
if (temp[i] == temp[j])
{
i--;
break;
}
}
}
#endregion
for (int i = 0, index = 0; i < x.GetLength(0); i++)
{
for (int j = 0; j < x.GetLength(1); j++)
{
for (int k = 0; k < x.GetLength(2); k++)
{
x[i, j, k] = temp[index++];
Console.Write(x[i, j, k] + " ");
}
Console.WriteLine();
}
}// i think it's correct code i've changed it