My single layer perceptrone is not working - c#

Here is code.
public class Adaline
{
private int _layer;
public int Layer { get { return _layer; } }
private int _epoch;
public int Epoch { get { return _epoch; } }
private double _error;
public double Error { get { return _error; } }
private double[] _weights;
public Adaline(int layer)
{
_layer = layer;
_weights = new double[layer];
Reset();
}
public void Reset()
{
Random r = new Random();
for (int i = 0; i < _layer; i++)
_weights[i] = r.NextDouble() - 0.5;
_error = 1;
}
public void Train(BasicTrainSet<double> trainset, double learnRate)
{
double ers = 0;
for(int p = 0; p < trainset.DataCount; p++)
{
double result = Compute(trainset.Input[p], true);
double error = trainset.Output[p] - result;
for (int i = 0; i < _weights.Length; i++)
{
_weights[i] += error * trainset.Input[p][i] * learnRate;
}
ers += Math.Abs(error);
}
_epoch++;
_error = ers;
}
public double Compute(double[] input, bool quan)
{
double result = 0;
for (int i = 0; i < _layer; i++)
result += Math.Tanh(_weights[i] * input[i]);
//double result = _weights.Zip(input, (a, b) => Math.Tanh(a * b)).Sum();
return quan ? (result >= 0 ? 1 : 0) : result;
}
}
When I tried to train and gate like this, it works like this.
Up four results are from this code
This is pretty weird, because there is not any problem with algorithm.
Weights are getting bigger and bigger. Where did i mistake?

In your code to compute the output of each neuron, you aren't applying the activation function correctly. You need to find the dot product between the weights and the inputs into each neuron then apply the activation function after. You are applying the activation function after each weighted accumulation, which is not correct.
Accumulate, then apply the activation function:
public double Compute(double[] input, bool quan)
{
double result = 0;
for (int i = 0; i < _layer; i++)
result += _weights[i] * input[i]; // Change - accumulate first
result = Math.Tanh(result); // Change - now apply activation function
return quan ? (result >= 0 ? 1 : 0) : result;
}

Related

Design and develop a single page ASP.NET web application that converts a given number

I keep getting the following error: Cannot implicitly convert type 'int' to 'string'. I'm using C# for an ASP.web application
public string binTodec(int num)
{
int binaryNumber = int.Parse(Console.ReadLine());
int decimalValue = 0;
int base1 = 1;
while (binaryNumber > 0)
{
int reminder = binaryNumber % 10;
binaryNumber = binaryNumber / 10;
decimalValue += reminder * base1;
base1 = base1 * 2;
}
Console.Write($"Decimal Value : {decimalValue} ");
Console.ReadKey();
return decimalValue;
}
Any idea what my issue is??
The following is an algorithm that should work for your purposes:
public string binToDec(string bin)
{
int result = 0;
int exp = 0;
for (int i = bin.Length - 1; i > -1; i--, exp++)
{
double baseVal = 2 * double.Parse((bin.Substring(i, 1)));
if (baseVal == 0) continue;
double expVal = (double)(exp);
result += (int)(Math.Pow(baseVal, expVal));
}
return result.ToString();
}

Selection sort method does not do anything C#

i'm trying to make a selection sort algorithm work using an implemented Data Array class with a swap method. The problem is when i try to run the code to see if it works nothing changes in the output and i'm seriously confused as to why that is. The numbers are randomly generated every time
public static void SelectionSort(DataArray items)
{
int index = 0;
double minValue = 0;
for(int i = 0; i < items.Length - 1; i++)
{
index = i;
minValue = items[i];
for(int j = i + 1; j < items.Length; j++)
{
if(minValue > items[j])
{
minValue = items[j];
index = j;
}
}
items.Swap(i, index, items[i], minValue);
}
My swap method
class MyDataArray:DataArray
{
double[] data;
public MyDataArray(int n, int seed)
{
data = new double[n];
length = n;
Random rand = new Random(seed);
for
(int i = 0; i < length; i++)
{
data[i] = rand.NextDouble();
}
}
public MyDataArray(int n)
{
data = new double[n];
length = n;
}
public override double this[int index]
{
get { return data[index]; }
}
public override void Swap(int i, int j, double a, double b)
{
data[i] = a;
data[j] = b;
}
}
}
Data Array class
abstract class DataArray
{
public int length;
public int Length { get { return length; } }
public abstract double this[int index] { get; }
public abstract void Swap(int i, int j, double a, double b);
public void Print(int n)
{
for (int i = 0; i < n; i++)
Console.Write(" {0:F3} ", this[i]);
Console.WriteLine();
}
}
When i try to run the code using this method
public static void Test_Array_List(int seed)
{
int n = 12;
MyDataArray myarray = new MyDataArray(n, seed);
Console.WriteLine("Before sorting");
myarray.Print(n);
Console.WriteLine("After sorting");
SelectionSort(myarray);
myarray.Print(n);
}
I get this result where nothing changes and i have no idea why
Before sorting
0.216 0.578 0.831 0.898 0.653 0.496 0.380 0.567 0.230 0.611 0.091 0.076
After sorting
0.216 0.578 0.831 0.898 0.653 0.496 0.380 0.567 0.230 0.611 0.091 0.076
Press any key to continue . .
Thank you in advanced
You should learn to use the debugger to diagnose these types of problems. Run through the program line-by-line, examining the variables and outputs of functions, to see where something doesn't work as expected.
That said, I suspect that your use of Swap is incorrect, since you are passing the values at i and j back to it in that order, so it's not really swapping anything. You can avoid this type of bug by just passing the indices:
public override void Swap(int i, int j)
{
var temp = data[i];
data[i] = data[j];
data[j] = temp;
}

.NET Stops on sorting and Icompare()

I'm having a problem with sorting and IComparer(). My program stops on it. I'm a beginner with C#.
Here is the part of the code where it stops:
public ArrayList ModelSort()
{
IComparer sorter = new R2SortHelper();
InnerList.Sort(sorter);
return InnerList;
}
private class R2SortHelper : System.Collections.IComparer
{
public int Compare(object x, object y)
{
double m1 = ((Model)x).R2() + ((Model)x).Valid().GetHashCode();
double m2 = ((Model)y).R2() + ((Model)y).Valid().GetHashCode();
if (m1 > m2)
return -1;
else if (m1 < m2)
return 1;
else
return 0;
}
}
Here is an error from console:
Unable to sort because the IComparer.Compare() method returns inconsistent results. Either a value does not compare equal to itself, or one value repeatedly compared to another value yields different results. IComparer: 'AMO.EnPI.AddIn.Utilities.ModelCollection+R2SortHelper'.
List of exceptions:
Exception Text
System.ArgumentException: Unable to sort because the IComparer.Compare() method returns inconsistent results. Either a value does not compare equal to itself, or one value repeatedly compared to another value yields different results. IComparer: 'AMO.EnPI.AddIn.Utilities.ModelCollection+R2SortHelper'.
at System.Array.SorterObjectArray.DepthLimitedQuickSort(Int32 left, Int32 right, Int32 depthLimit)
at System.Array.SorterObjectArray.DepthLimitedQuickSort(Int32 left, Int32 right, Int32 depthLimit)
at System.Array.Sort(Array keys, Array items, Int32 index, Int32 length, IComparer comparer)
at System.Collections.ArrayList.Sort(Int32 index, Int32 count, IComparer comparer)
at System.Collections.ArrayList.Sort(IComparer comparer)
at AMO.EnPI.AddIn.Utilities.ModelCollection.ModelSort() in C:\ENPI\EnPI\AMO.EnPI-5.0\AMO.EnPI.Utilities\Analytics.cs:line 961
at AMO.EnPI.AddIn.ModelSheet.WriteResultsTable(Int32 n, Boolean top) in C:\ENPI\EnPI\AMO.EnPI-5.0\AMO.EnPI.AddIn\ModelSheet.cs:line 146
at AMO.EnPI.AddIn.ModelSheet.Populate() in C:\ENPI\EnPI\AMO.EnPI-5.0\AMO.EnPI.AddIn\ModelSheet.cs:line 60
at AMO.EnPI.AddIn.ThisAddIn.plotEnPI(ListObject LO) in C:\ENPI\EnPI\AMO.EnPI-5.0\AMO.EnPI.AddIn\ThisAddIn.cs:line 318
at AMO.EnPI.AddIn.RegressionControl.runFunction(Object sender, EventArgs e) in C:\ENPI\EnPI\AMO.EnPI-5.0\AMO.EnPI.AddIn\RegressionControl.cs:line 817
at AMO.EnPI.AddIn.CO2EmissionControl.btnCalculate_Click(Object sender, EventArgs e) in C:\ENPI\EnPI\AMO.EnPI-5.0\AMO.EnPI.AddIn\CO2EmissionControl.cs:line 148
My model class:
public class Model
{
public int ModelNumber { get; set; }
public double[] Ys { get; set; }
public double[,] Xs { get; set; }
public string[] VariableNames { get; set; }
public double RMSError { get; set; }
public double[] Coefficients { get; set; }
public Model()
{
ModelNumber = 0;
Ys = null;
Xs = null;
VariableNames = null;
RMSError = 0;
Coefficients = null;
}
public Model(int ModelNumber, double[] Ys, double[,] Xs, string[] VariableNames)
{
RMSError = 0;
Coefficients = null;
// run LLS
int info;
double[] c;
alglib.lsfitreport rep;
try
{
alglib.lsfitlinear(Ys, Xsplusone(), out info, out c, out rep);
}
catch
{
throw;
}
Coefficients = c;
RMSError = rep.rmserror;
}
public void Run() //double[] Ys, double[,] Xs, string[] VariableNames)
{
RMSError = 0;
Coefficients = null;
if (Ys != null && Xs != null)
{
// run LLS
int info;
double[] c;
alglib.lsfitreport rep;
try
{
alglib.lsfitlinear(Ys, Xsplusone(), out info, out c, out rep);
}
catch
{
throw;
}
Coefficients = c;
RMSError = rep.rmserror;
}
}
public int N()
{
return Ys.Count();
}
public int df()
{
return N() - k() - 1;
}
public int k()
{
return VariableNames.Count();
}
public double TotalSS()
{
// compute total sum of squares
double ybar = Ys.Average();
double sst = 0;
for (int i = Ys.GetLowerBound(0); i <= Ys.GetUpperBound(0); i++)
{
sst += Math.Pow(Ys[i] - ybar, 2);
}
return sst;
}
public double ResidualSS ()
{
return ( N() * Math.Pow( RMSError, 2));
}
public double R2()
{
return (1 - (ResidualSS() / TotalSS()));
}
public double AdjustedR2()
{
return (1 - (((1 - R2()) * (N() - 1)) / (N() - k() - 1)));
}
public double F()
{
return ( (R2() / k()) / ((1 - R2()) / (N() - k() - 1)));
}
public double ModelPValue()
{
double modelP = 0;
double modelF = F();
if (modelF < 0) modelF = 0;
try
{
modelP = alglib.fcdistribution(N() - df() - 1, df(), modelF);
}
catch (alglib.alglibexception e)
{
}
return modelP;
}
public bool Valid()
{
// Model validity criteria, from the SEP M&V protocol:
// The model p-value must be less than 0.1
// All variables must have p-values less than 0.2
// At least one variable must have a p-value of less than 0.1
// The R2 value must be greater than 0.5
double[] ps = PValues();
bool varsvalid = true;
bool varlowexists = false;
for (int i = 0; i < ps.Count(); i++)
{
if (ps[i] <= Constants.PVALUE_THRESHOLD)
varlowexists = true;
if (ps[i] > Constants.PVALUE_HIGH)
varsvalid = false;
}
if (!varlowexists)
return false;
if (!varsvalid)
return false;
if (ModelPValue() > Constants.PVALUE_THRESHOLD)
return false;
if (R2() < Constants.R2VALUE_MIN)
return false;
return true;
}
public string Formula()
{
string formula = "";
int offset = Coefficients.GetLowerBound(0) - VariableNames.GetLowerBound(0);
for (int i = Coefficients.GetLowerBound(0); i < Coefficients.GetUpperBound(0); i++)
{
formula += "(" + Coefficients[i].ToString("0.0000") + " * " + ExcelHelpers.CreateValidFormulaName(VariableNames[i - offset]) + ") + ";
// formula += "(" + Coefficients[i].ToString() + " * " + ExcelHelpers.CreateValidFormulaName(VariableNames[i - offset]) + ") + ";
}
formula += Coefficients[Coefficients.GetUpperBound(0)].ToString("0.00");
return formula;
}
public double[,] Xsplusone()
{
return DataHelper.arrayAddIdentity(Xs, 0, 1); // add on a column of ones for the intercept
}
public double[] PredictedYs()
{ // compute the predicted ys
double[] yhat = new double[N()];
double[,] xs = Xsplusone();
double[] c = Coefficients;
for (int i = 0; i < N(); i++)
{
yhat[i] = 0;
for (int j = 0; j < k() + 1; j++)
{
yhat[i] += xs[i, j] * c[j];
}
}
return yhat;
}
public double[,] CovarianceMatrix()
{
// compute the coefficient covariance matrix
double[,] twodYs = DataHelper.dbl2DArray(Ys);
double[,] XYs = DataHelper.dblarrayUnion(Xs, twodYs);
double[,] cov;
int info;
alglib.linearmodel lm;
alglib.lrreport rpt;
try
{
alglib.lrbuild(XYs, N(), k(), out info, out lm, out rpt);
cov = rpt.c;
}
catch
{
throw;
}
return cov;
}
public double[] StandardErrors()
{
// compute the x std errors and p-values
double[,] cov = CovarianceMatrix();
double[] se = new double[k()];
if (cov.GetLength(0) > 0 && cov.GetLength(1) > 0)
{
for (int j = 0; j < k(); j++)
{
se[j] = Math.Sqrt(cov[j, j]);
}
}
return se;
}
public double[] PValues()
{
double[] c = Coefficients;
double[,] cov = CovarianceMatrix();
double[] se = StandardErrors();
double[] pv = new double[k()];
if (cov.GetLength(0) > 0 && cov.GetLength(1) > 0)
{
for (int j = 0; j < k(); j++)
{
se[j] = Math.Sqrt(cov[j, j]);
try
{
pv[j] = 2 * (1 - alglib.studenttdistribution(df(), Math.Abs(c[j] / se[j])));
}
catch
{
}
}
}
return pv;
}
public string AICFormula()
{
return "";
}
//Added By Suman for SEP Validation changes
public string[] SEPValidationCheck()
{
string[] sepChk = new string[k()];
for (int cnt = 0; cnt < sepChk.Length; cnt++)
{
if (Valid() == true)
{
sepChk[cnt] = "Pass";
}
else
{
sepChk[cnt] = "Fail";
}
}
return sepChk;
}
}
Here is GetHashCode():
public override int GetHashCode()
{
return x.GetHashCode() ^ y.GetHashCode();
}
My R2():
public double R2()
{
return (1 - (ResidualSS() / TotalSS()));
}
For the majority of types, you can't sort by GetHashCode() since the hash code calculations aren't necessarily going to sort in the same order as the value. You can only sort on GetHashCode() reliably when it is the value itself (such as int), but at that point there isn't any point in getting the hash code since you already have the value. Also you didn't show what R2() and Valid() methods do, so who knows what kind of unholyness is going on in there.
EDIT (OP updated code):
Your GetHashCode() usage is definitely not sortable. Nor is adding a boolean to a double. 5 + 0 vs. 2 + 1 is not going to sort correctly (assuming you want the falses up front?)
Just use ((Model)x).R2() vs ((Model)y).R2() as the comparison, if you want the falses or trues up front, you can add something like:
if (x.Valid && !y.Valid)
return 1;
if (!x.Valid && y.Valid)
return -1;
//then do your R2 comparisons here.
That preamble will cause the non valids to always come first and then sort by R2s. You can reverse if you want to go the other way.
Your .Valid() method is returning boolean, and then you go to find hash code. Is this expected from your code?
Basically, you are doing some double value + boolean.GetHashCode(). Solution would be to not use .Valid() in your right side expression. Check that separately.
private class R2SortHelper : System.Collections.IComparer
{
public int Compare(object x, object y)
{
Model xModel = (Model)x;
Model yModel = (Model)y;
if((Model.Valid()==true) && (yModel.Valid()==true))
{
double m1 = xModel.R2() + xModel.GetHashCode();
double m2 = yModel.R2() + yModel.GetHashCode();
return (m1 > m2) ? -1 : ((m1 < m2) ? 1 :0);
}
return 0;
}
}

Raising a number to a power using only addition

I am trying to raise a number to a power using only addition but it does not work, it just raises a number bigger than the original.Here is my code:
private void ExpOperation()
{
result = 0;
num01 = Int32.Parse(inpu01.Text);
num02 = Int32.Parse(inpu02.Text);
int a = num02;
num02 = num01;
int i = 1;
while (i <= a)
{
result = SimpleMulti(num01,num02);
num01 = result;
i++;
}
result_Text.Text = result.ToString();
}
private int SimpleMulti (int num1, int num2)
{
int c = 0;
int i = 1;
while (i <= num2)
{
c += num1;
i++;
}
return c;
}
private int SimpleMulti (int x, int y)
{
int product = 0; //result of multiply
for (int i = 0; i<y; i++){
product += x;
}
//multiplication is repeated addition of x, repeated y times
//the initial solution with a while loop looks correct
return product;
}
private int ExpOperation(int x, int exponent)
{
int result = 1;
if (exponent == 0) {
return result; //anything that powers to 0 is 1
}
else
{
for (int i = 0; i < exponent; i++){
result = SimpleMulti(result, x);
//loop through exponent, multiply result by initial number, x
//e.g. 2^1 = 2, 2^2 = result of 2^1 x 2, 2^3 = result of 2^2 x 2
}
}
return result;
}
Keep in mind that this method does not support negative exponent, which deals with division, but instead of using SimpleMulti, you can create a method for SimpleDivide which uses subtraction instead. The principle is the same
I don't think this question is quite relevant to the main reason of this site, however I got a solution:
public long ExpOperation(int a, int b)
{
long result = 0;
long temp = 0;
for (int i = 1; i <= b; i++) // Executes a full loop when we have successfully multiplied the base number "a" by itself
{
for (int j = 1; j <= a; j++) // Increase the result by itself for a times to multiply the result by itself
result += temp;
temp = result:
}
return result;
}
Because x^y = x * x^(y-1), it can be solved recursively. Since SimpleMulti in question returns integer, I assume both base and exponent are non-negative integer.
private static int PowerWithAddition(int x, int y)
{
if(y == 0){
return 1;
}
var y1 = PowerWithAddition(x, y - 1);
var sum = 0;
for (int i = 0; i < y1; i++)
{
sum += x;
}
return sum;
}

Unit Test these methods?

Hi I was wondering how I could unit test the methods below:
public float calcNP()
{
int rowcount = dataGridView1.Rows.Count;
int[] colB = new int[rowcount];
float[] NP = new float[rowcount];
float avgNP = 0;
for (int i = 0; i < rowcount; i++)
{
colB[i] = Convert.ToInt32(dataGridView1.Rows[i].Cells[5].Value);
}
float min = colB.Min();
float max = colB.Max();
float a = 1, b = 10;
for (int i = 0; i < rowcount; i++)
{
NP[i] = (a + (colB[i] - min) * (b - a)) / (max - min);
avgNP = NP[i] + avgNP;
}
avgNP = (avgNP / rowcount) * 100;
return avgNP;
}
and also the following
public float calcIFact()
{
float ftp = calcFTP();
float NP = calcNP();
float IntFact = NP / ftp;
return IntFact;
}
and this
public float calcFTP()
{
float ftp = 0;
if (chkFTP.Checked == true)
{
// ftp =(float)Convert.ToDouble(txtFTP.Text)/100;
ftp = (float)Convert.ToDouble(txtFTP.Text);
}
if (chkFTP.Checked == false)
{
int rowcount = dataGridView1.Rows.Count;
int[] colB = new int[rowcount];
for (int i = 0; i < rowcount; i++)
{
colB[i] = Convert.ToInt32(dataGridView1.Rows[i].Cells[5].Value);
}
// ftp = colB.Max() / 100;
ftp = colB.Max();
}
If someone could give me some examples that would be great.
Basically just need some simple tests for the calculations
We are telling you to do this:
// New method, not depending on a gridview. Testable.
public float calcNP_pure(int[] colB)
{
float[] NP = new float[colB.Length];
float avgNP = 0;
float min = colB.Min();
float max = colB.Max();
float a = 1, b = 10;
for (int i = 0; i < rowcount; i++)
{
NP[i] = (a + (colB[i] - min) * (b - a)) / (max - min);
avgNP = NP[i] + avgNP;
}
avgNP = (avgNP / rowcount) * 100;
return avgNP;
}
// Not testable
public float calcNP()
{
int rowcount = dataGridView1.Rows.Count;
int[] colB = new int[rowcount];
for (int i = 0; i < rowcount; i++)
{
colB[i] = Convert.ToInt32(dataGridView1.Rows[i].Cells[5].Value);
}
return calcNP_pure(colB);
}
This new method should also go into a new class and not sit on a form or some other UI-element. The best practice is to program against interfaces and to inject required dependencies into the objects:
public interface INpCalculator
{
float CalcNP(int[] values);
}
public class NpCalculator : INpCalculator
{
public float CalcNP(int[] values)
{
...
return ...;
}
}
public partial class Form1 : Form
{
private INpCalculator _npCalculator;
public Form1(INpCalculator npCalculator)
{
InitializeComponent();
_npCalculator = npCalculator;
}
private float CalcNP()
{
int[] colB = dataGridView1.Rows
.Cast<DataGridViewRow>()
.Select(row => row.Cells[5].Value)
.ToArray();
return _npCalculator.CalcNP(colB);
}
}
Now the calculator is testable without the need to open any form:
[TestMethod]
public void TestNpCalculator()
{
// Arrange
var sut = new NpCalculator();
var values = new int[] { 12, 7, 15, 3 };
// Act
float result = sut.CalcNP(values);
// Assert
Assert.AreEqual(123.456f, result);
}
Btw: sut stands for "system under test".
In current state of the method, your unit tests are going to require manually create datagrid object and populate values as per your testing scenario. As suggested by Daniel, your method "public float calcNP()" should not use data grid, instead of that you can pass an array of integers to the method (pass only values which you are going to use in calculation)

Categories

Resources