DL4J linear regression - neural-network

I am new in neural networks. I am trying to implement and train simple neural network with DL4j. My function:
y = x * 2 + 300
My vision
My result
Parameters:
public final int seed = 12345;
public final int iterations = 1;
public final int nEpochs = 1;
public final int batchSize = 1000;
public final double learningRate = 0.01;
public final Random rng = new Random(seed);
public final int numInputs = 2;
public final int numOutputs = 1;
public final double maxX = 100;//xmax = 100; ymax=500.
public final double scale = 500;//for scale out x and y.
Network configuration:
public MultiLayerConfiguration createConf() {
return new NeuralNetConfiguration.Builder()
.seed(seed)
.iterations(iterations)
.optimizationAlgo(OptimizationAlgorithm.STOCHASTIC_GRADIENT_DESCENT)
.learningRate(learningRate)
.weightInit(WeightInit.XAVIER)
.updater(new Nesterovs(0.9))
.list()
.layer(0, new OutputLayer.Builder(LossFunctions.LossFunction.MSE)
.activation(Activation.IDENTITY)
.nIn(numInputs).nOut(numOutputs).build())
.pretrain(false).backprop(true).build();
}
Training data:
public DataSetIterator generateTrainingData() {
List<DataSet> list = new ArrayList<>();
for (int i = 0; i < batchSize; i++) {
double x = rng.nextDouble() * maxX * (rng.nextBoolean() ? 1 : -1);
double y = y(x);
list.add(
new DataSet(
Nd4j.create(new double[]{x / scale, 1}),
Nd4j.create(new double[]{y / scale})
)
);
}
return new ListDataSetIterator(list, batchSize);
}
Testing:
public void test() {
final MultiLayerNetwork net = new MultiLayerNetwork(createConf());
net.init();
net.setListeners(new ScoreIterationListener(1));
for (int i = 0; i < nEpochs; i++) {
net.fit(generateTrainingData());
}
int idx = 0;
double x[] = new double[19];
double y[] = new double[19];
double p[] = new double[19];
for (double i = -90; i < 100; i += 10) {
x[idx] = i;
y[idx] = y(i);
p[idx] = scale * net.output(Nd4j.create(new double[]{i / scale, 1})).getDouble(0, 0);
idx++;
}
plot(x, y, p);
}
Please tell me what i am doing wrong or if i have incorrect vision...
Thank you in advance,
Regards,
Minas

Take a look at this example:
https://github.com/deeplearning4j/dl4j-examples/tree/master/dl4j-examples/src/main/java/org/deeplearning4j/examples/feedforward/regression
Few tips:
Use our built in normalization tools. Don't do this yourself.
Our normalization tools allow you to normalize labels as well.
Turn minibatch off (set minibatch(false) on the neural net config near the top)
Ultimately you still aren't actually doing "minibatch learning"
Also, you're regenerating the dataset each time. There's no need to do that. Just create it once and pass it in to fit.
For visualization purposes, use the restore mechanism I mentioned earlier (This is in the example, you can pick 1 of any of the normalizers like MinMaxScalar, NormalizeStandardize,.. etc)
Your iterations are also wrong. Just keep that value at 1 and keep your for loop. Otherwise you're just overfitting and spending way more of your training time then you need to. An "iteration" is actually the number of updates you want to run per fit call on the same dataset. Next release we are getting rid of that option anyways.

Related

Holes in Mesh only showing from one side

For a sailing game I'm working on, I've added functionality to programmatically create damage holes in a mesh (e.g. cannonball holes in a sail). This is largely based on the method here (link to the example code here)
private void MessWithMesh() {
filter = this.transform.parent.gameObject.GetComponent<MeshFilter>();
mesh = filter.mesh;
filter.mesh = GenerateMeshWithHoles();
}
private IEnumerator GenerateTrisWithVertex() {
// Destroying the sail won't work until this has finished, but it only takes a second or two so I don't think anybody will notice.
trisWithVertex = new List<int>[origvertices.Length];
for (int i = 0; i <origvertices.Length; ++i)
{
trisWithVertex[i] = ArrayHelper.IndexOf(origtriangles, i);
yield return null;
}
yield return null;
}
Mesh GenerateMeshWithHoles()
{
float damageRadius = 1f;
Transform parentTransform = this.transform.parent.transform;
Hole[] holes = this.GetComponentsInChildren<Hole>();
foreach (Hole hole in holes) {
Vector3 trackPos = hole.transform.position;
float closest = float.MaxValue;
int closestIndex = -1;
int countDisabled = 0;
damageRadius = hole.diameter;
for (int i = 0; i <origvertices.Length; ++i)
{
Vector3 v = new Vector3(origvertices[i].x * parentTransform.localScale.x, origvertices[i].y * parentTransform.localScale.y, origvertices[i].z * parentTransform.localScale.z) + parentTransform.position;
Vector3 difference = v - trackPos;
if (difference.magnitude < closest)
{
closest = difference.magnitude;
closestIndex = i;
}
if (difference.magnitude < damageRadius)
{
for (int j = 0; j <trisWithVertex[i].Count; ++j)
{
int value = trisWithVertex[i][j];
int remainder = value % 3;
trianglesDisabled[value - remainder] = true;
trianglesDisabled[value - remainder + 1] = true;
trianglesDisabled[value - remainder + 2] = true;
countDisabled++;
}
}
}
// If no triangles were removed, then we'll just remove the one that was closest to the hole.
// This shouldn't really happen, but in case the hole is off by a bit from where it should have hit the mesh, we'll do this to make sure there's at least a hole.
if (countDisabled == 0 && closestIndex > -1) {
Debug.Log("Removing closest vertex: " + closestIndex);
for (int j = 0; j < trisWithVertex[closestIndex].Count; ++j)
{
int value = trisWithVertex[closestIndex][j];
int remainder = value % 3;
trianglesDisabled[value - remainder] = true;
trianglesDisabled[value - remainder + 1] = true;
trianglesDisabled[value - remainder + 2] = true;
}
}
}
triangles = ArrayHelper.RemoveAllSpecifiedIndicesFromArray(origtriangles, trianglesDisabled).ToArray();
mesh.SetTriangles(triangles, 0);
for (int i = 0; i <trianglesDisabled.Length; ++i)
trianglesDisabled[i] = false;
return mesh;
}
When a cannonball hits the sail, I add a Hole object at the location of the impact, and I call MessWithMesh. The holes are often generated correctly, but many times they're only visible from one side of the sail (it looks fully intact from the other side). It's often visible from the opposite side of the sail that the cannonball impacted (the far side, not the near side), if that's at all helpful. The ship I'm using is this free asset.
I'm not really familiar with meshes, so I don't really understand what's going on.

Microphone, gain value and spectrum values do not sync using Unity

I am making a simple voice visualization program. My goals are:
Playback microphone input
Visualize voice spectrum and gain in real time
Here is my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class VisualizeVoice : MonoBehaviour
{
private const int NUM_SPECTRUM_SAMPLES = 256;
private const int NUM_SPECTRUM_BARS = 32;
private const int NUM_PCM_SAMPLES = 16000;
private const float BAR_DROP_SPEED = 1e-3f;
private const int NUM_SAMPLES_TO_AVERAGE = 8;
private string _deviceName;
private float[] _spectrumData = new float[NUM_SPECTRUM_SAMPLES];
private float[] _fPCMData = new float[NUM_PCM_SAMPLES];
private float _gain = 0;
private AudioClip _audio; // Audio from microphone
private AudioSource _playback; // To play the audio from microphone
// For visualization
private GameObject[] _spectrumBars = new GameObject[NUM_SPECTRUM_BARS];
private GameObject _gainBar;
// Start is called before the first frame update
void Start()
{
if (Microphone.devices.Length == 0) {
Debug.LogError("No Microphone");
return;
}
_deviceName = Microphone.devices[0];
Debug.Log("Current microphone is " + _deviceName);
if ((_playback = this.GetComponent<AudioSource>()) == null) {
_playback = this.gameObject.AddComponent<AudioSource>();
}
_playback.loop = true;
_playback.bypassEffects = true;
_playback.bypassListenerEffects = true;
_playback.bypassReverbZones = true;
_playback.priority = 0;
_playback.pitch = 1;
_playback.clip = _audio = Microphone.Start(_deviceName, true, 1, AudioSettings.outputSampleRate);
// Sync microphone and playback, but it always fails
float waitTime = 0;
while (!(Microphone.GetPosition(_deviceName) > 0) && waitTime <= 2)
waitTime += Time.deltaTime;
if (waitTime > 2) {
Debug.LogError("time out waiting for microphone");
}
_playback.Play();
InitVisualization();
}
// Update is called once per frame
void Update()
{
// Get PCM data and calculate gain
var audioPosition = Microphone.GetPosition(_deviceName);
_audio.GetData(_fPCMData, audioPosition);
UpdateGain();
// Get spectrum data
_playback.GetSpectrumData(_spectrumData, 0, FFTWindow.BlackmanHarris);
// Update visualization
UpdateVisualization();
}
private void InitVisualization()
{
// Initialize spectrum bars
for (int ibar = 0; ibar < NUM_SPECTRUM_BARS; ibar++) {
_spectrumBars[ibar] = GameObject.CreatePrimitive(PrimitiveType.Cube);
_spectrumBars[ibar].transform.parent = this.transform;
_spectrumBars[ibar].transform.localPosition = new Vector3(ibar, 0, 0);
_spectrumBars[ibar].transform.localScale = new Vector3(1, 0, 1);
}
// Initialize gain bar
_gainBar = GameObject.CreatePrimitive(PrimitiveType.Cube);
_gainBar.transform.parent = this.transform;
_gainBar.transform.localPosition = new Vector3(-5, 0, 0);
_gainBar.transform.localScale = new Vector3(4, 0, 1);
// Overall dimension
this.transform.localScale = new Vector3(0.2f, 10.0f, 0.2f);
}
private void UpdateVisualization()
{
// Update spectrum bars
int nSamplesPerBar = NUM_SPECTRUM_SAMPLES / NUM_SPECTRUM_BARS;
for (int ibar = 0; ibar < NUM_SPECTRUM_BARS; ibar++) {
// Calculate value of each bar
float value = 0;
for (int isample = 0; isample < nSamplesPerBar; isample++) {
value += _spectrumData[ibar * nSamplesPerBar + isample];
}
value /= nSamplesPerBar;
// Use current value if increasing, or slowly drop previous value if decreasing
float prevValue = _spectrumBars[ibar].transform.localScale.y;
if (value < prevValue)
value = prevValue - BAR_DROP_SPEED;
// Y scale is set to value
_spectrumBars[ibar].transform.localScale = new Vector3(1, value, 1);
}
// Update gain bar
_gainBar.transform.localScale = new Vector3(4, _gain, 1);
}
private void UpdateGain()
{
_gain = 0;
for(int i = 0; i < NUM_SAMPLES_TO_AVERAGE; i++) {
_gain += Mathf.Abs(_fPCMData[NUM_PCM_SAMPLES - i - 1]);
}
_gain /= NUM_SAMPLES_TO_AVERAGE;
}
}
Here are my questions:
I can't use while (!Microphone.GetPosition(_deviceName) > 0)); to avoid latency from microphone to speaker. If I use it, my application just freezes. If I add code to allow time-out, it has time-out every time.
The gain bar seems irrelevant with my voice. I don't know if my calculation is right.
I'm not sure if I need to average over multiple samples calculating gains, and how many samples I need to average over. I need this gain value later to detect silent moments and cut audio data.
To 1.
You can. Unity allows to define Start as a Coroutine
private IEnumerator Start()
{
...
}
On this way you can use a non blocking
while (!Microphone.GetPosition(_deviceName) > 0))
{
yield return null;
}

Are there any examples of pedestrian modelling in repast simphony?

Are there any examples of pedestrian modelling in repast simphony? I am novice in repast and was trying to model a simple pedestrian movement simulation. Any pointers to useful resources/ examples?
Andrew Crook's blog GIS and Agent-Based Modeling (http://www.gisagents.org/) has lots of interesting links to pedestrian models. I think there are even some specific to Repast.
Repast isn't the best for open libraries, but I've had some luck searching GitHub. Here's a basic ped agent I built once, you'll have to build a context with a scheduler class to call the pedestrians:
context:
public class RoadBuilder extends DefaultContext<Object> implements ContextBuilder<Object> {
context.setId("driving1");
ContinuousSpaceFactory spaceFactory =
ContinuousSpaceFactoryFinder.createContinuousSpaceFactory(null);
ContinuousSpace<Object> space =
spaceFactory.createContinuousSpace("space",context, new SimpleCartesianAdder<Object>(),
new StrictBorders(), roadL, worldW);
clock = RunEnvironment.getInstance().getCurrentSchedule();
flowSource = new Scheduler();
context.add(flowSource);
return context;
}
the scheduler:
public class Scheduler {
static ArrayList<Ped> allPeds;
#ScheduledMethod(start = 1, interval = 1, priority = 1)
public void doStuff() {
Ped addedPed = addPed(1);
allPeds.add(addedPed);
for (Ped a : allPeds) {
a.calc();}
for (Ped b : allPeds) {
b.walk();}
public Ped addPed(int direction) {
Context<Object> context = ContextUtils.getContext(this);
ContinuousSpace<Object> space = (ContinuousSpace<Object>) context.getProjection("space");
Ped newPed = new Ped(space,direction);
context.add(newPed);
space.moveTo(newPed,xPlacement,yPlacement);
newPed.myLoc = space.getLocation(newPed);
return(newPed);
}
The pedestrians - This is based on a "generalized force model" (source: Simulating Dynamical Features of Escape Panic - Helbing, Farkas, and Vicsek - https://arxiv.org/pdf/cond-mat/0009448.pdf)
and here's the pedestrian class
public class Ped {
private ContinuousSpace<Object> space;
private List<Double> forcesX, forcesY;
private NdPoint endPt;
private Random rnd = new Random();
private int age;
private double endPtDist, endPtTheta, critGap;
private double side = RoadBuilder.sidewalk;
private double wS, etaS, wV, etaV, sigR; //errors
private double m, horiz, A, B, k, r; //interactive force constants (accT is also)
public NdPoint myLoc, destination;
public double[] v, dv, newV;
public double xTime, accT, maxV, xLoc, yLoc;
public int dir; // dir = 1 walks up, -1 walks down
public void calc() {
myLoc = space.getLocation(this);
dv = accel(myLoc,dir,destination);
newV = sumV(v,dv);
newV = limitV(newV);
}
public void walk() {
v = newV;
move(myLoc,v);
}
public double[] accel(NdPoint location, int direct, NdPoint endPt) {
forcesX = new ArrayList<Double>();
forcesY = new ArrayList<Double>();
double xF, yF;
double[] acc;
xF = yF = 0;
//calculate heading to endpoint
endPtDist = space.getDistance(location, endPt);
double endPtDelX = endPt.getX()-location.getX();
endPtTheta = FastMath.asin((double)direct*endPtDelX/endPtDist);
if (direct == -1) {
endPtTheta += Math.PI;}
//calculate motive force
Double motFx = (maxV*Math.sin(endPtTheta) - v[0])/accT;
Double motFy = (maxV*Math.cos(endPtTheta) - v[1])/accT;
forcesX.add(motFx);
forcesY.add(motFy);
//calculate interactive forces
//TODO: write code to make a threshold for interaction instead of the arbitrary horizon
for (Ped a : Scheduler.allPeds) {
if (a != this) {
NdPoint otherLoc = space.getLocation(a);
double otherY = otherLoc.getY();
double visible = Math.signum((double)dir*(otherY-yLoc));
if (visible == 1) { //peds only affected by those in front of them
double absDist = space.getDistance(location, otherLoc);
if (absDist < horiz) {
double delX = location.getX()-otherLoc.getX();
double delY = location.getY()-otherLoc.getY();
double delXabs = Math.abs(delX);
double signFx = Math.signum(delX);
double signFy = Math.signum(delY);
double theta = FastMath.asin(delXabs/absDist);
double rij = r + a.r;
Double interFx = signFx*A*Math.exp((rij-absDist)/B)*Math.sin(theta)/m;
Double interFy = signFy*A*Math.exp((rij-absDist)/B)*Math.cos(theta)/m;
forcesX.add(interFx);
forcesY.add(interFy);}}}}
//sum all forces
for (Double b : forcesX) {
xF += b;}
for (Double c : forcesY) {
yF += c;}
acc = new double[] {xF, yF};
return acc;
}
public void move(NdPoint loc, double[] displacement) {
double[] zero = new double[] {0,0};
double yl = loc.getY();
if (displacement != zero) {
space.moveByDisplacement(this,displacement);
myLoc = space.getLocation(this);}
}
public double[] limitV(double[] input) {
double totalV, norm;
if (this.dir == 1) {
if (input[1] < 0) {
input[1] = 0;}}
else {
if (input[1] > 0) {
input[1] = 0;}}
totalV = Math.sqrt(input[0]*input[0] + input[1]*input[1]);
if (totalV > maxV) {
norm = maxV/totalV;
input[0] = input[0]*norm;
input[1] = input[1]*norm;}
return input;
}
public double[] sumV(double[] a, double[] b) {
double[] c = new double[2];
for (int i = 0; i < 2; i++) {
c[i] = a[i] + b[i];}
return c;
}
public Ped(ContinuousSpace<Object> contextSpace, int direction) {
space = contextSpace;
maxV = rnd.nextGaussian() * UserPanel.pedVsd + UserPanel.pedVavg;
dir = direction; // 1 moves up, -1 moves down
v = new double[] {0,(double)dir*.5*maxV};
age = 0;
//3-circle variables - from Helbing, et al (2000) [r from Rouphail et al 1998]
accT = 0.5/UserPanel.tStep; //acceleration time
m = 80; //avg ped mass in kg
horiz = 5/RoadBuilder.spaceScale; //distance at which peds affect each other
A = 2000*UserPanel.tStep*UserPanel.tStep/RoadBuilder.spaceScale; //ped interaction constant (kg*space units/time units^2)
B = 0.08/RoadBuilder.spaceScale; //ped distance interaction constant (space units)
k = 120000*UserPanel.tStep*UserPanel.tStep; //wall force constant
r = 0.275/RoadBuilder.spaceScale; //ped radius (space units)
}
}

Dynamically adding tiles to a grid based map

I want to have an infinitely explorable map. The plan is to create categories of game tiles (roads, obstacles, buildings), and randomly choose a category of game tile to be added when the player approaches the edge of the existing set of tiles. Tiles will also be destroyed once the player is 2 grid squares away from that tile. Currently I am using a multidimensional array that requires a size initializer.
What I have so far:
public class GameManager : MonoBehaviour
{
private GameObject[,] tileArray;
public GameObject groundTile;
public GameObject player;
private int tileSize = 80;
private int nextFarX = 1;
private int nextFarZ = 1;
private int nextNearX = -1;
private int nextNearZ = -1;
private float padding = .1f;
private int arrayOffset;
private int arrayDimension;
// Use this for initialization
void Start ()
{
arrayDimension = 200;
arrayOffset = arrayDimension / 2;
tileArray = new GameObject[,];
this.AddCubeAt(0, 0);
}
// Update is called once per frame
void Update () {
var x = Convert.ToInt32(player.transform.position.x / tileSize);
var z = Convert.ToInt32(player.transform.position.z / tileSize);
for (int i = -1; i < 2; i++)
{
for (int j = -1; j < 2; j++)
{
var checkX = x + i;
var checkZ = z + j;
if (tileArray[checkX + arrayOffset, checkZ + arrayOffset] == null)
{
//player is less than 2 tiles away from this grid, add a tile
this.AddCubeAt(checkX, checkZ);
}
}
}
// feels like a hack, but it will remove tiles that are not touching the tile that the player occupies
for (int i = 0; i < 6; i++)
{
for (int j = 0; j < 6; j++)
{
if (i == 0 | i == 5 | j == 0 | j == 5)
{
if (tileArray[x + (i-2) + arrayOffset, z + (j-2) + arrayOffset] != null)
{
Destroy(tileArray[x + (i - 2) + arrayOffset, z + (j - 2) + arrayOffset]);
tileArray[x + (i - 2) + arrayOffset, z + (j - 2) + arrayOffset] = null;
}
}
}
}
}
private void AddCubeAt(int x, int z)
{
var pos = new Vector3(x * tileSize, 0, z * tileSize);
var rot = Quaternion.identity;
GameObject newCube = (GameObject)Instantiate(groundTile, pos, rot);
tileArray[x + arrayOffset, z + arrayOffset] = newCube;
}
}
What is a better way to approach this?
You should familiarize yourself with Graph Data Structure (not adjacency matrix implementation). It's much more appropriate for this task. And, I would solve this
Tiles will also be destroyed once the player is 2 grid squares away from that tile
in another way: Every time player changed his position I would start DFS on target depth (in your case it's 2) and remove found tiles.
Decided to go with a simple Dictionary and methods to query/update it:
private GameObject RetrieveTileAt(int x, int z)
{
string key = string.Format("{0}.{1}", x, z);
if (tileDictionary.ContainsKey(key))
{
return tileDictionary[key];
}
else
{
return null;
}
}
private void InsertTileAt(int x, int z, GameObject tile)
{
string key = string.Format("{0}.{1}", x, z);
tileDictionary[key] = tile;
}
It is not an infinitely sized grid, (int min + int max)squared, but it should be far more than I need.

Java based Neural Network --- how to implement backpropagation

I am building a test neural network and it is definitely not working. My main problem is backpropagation. From my research, I know that it is easy to use the sigmoid function. Therefore, I update each weight by (1-Output)(Output)(target-Output) but the problem with this is what if my Output is 1 but my target is not? If it is one at some point then the weight update will always be 0...For now I am just trying to get the darn thing to add the inputs from 2 input neurons, so the optimal weights should just be 1 as the output neuron simply adds its inputs. I'm sure I have messed this up in lots of places but here is my code:
public class Main {
public static void main(String[] args) {
Double[] inputs = {1.0, 2.0};
ArrayList<Double> answers = new ArrayList<Double>();
answers.add(3.0);
net myNeuralNet = new net(2, 1, answers);
for(int i=0; i<200; i++){
myNeuralNet.setInputs(inputs);
myNeuralNet.start();
myNeuralNet.backpropagation();
myNeuralNet.printOutput();
System.out.println("*****");
for(int j=0; j<myNeuralNet.getOutputs().size(); j++){
myNeuralNet.getOutputs().get(j).resetInput();
myNeuralNet.getOutputs().get(j).resetOutput();
myNeuralNet.getOutputs().get(j).resetNumCalled();
}
}
}
}
package myneuralnet;
import java.util.ArrayList;
public class net {
private ArrayList<neuron> inputLayer;
private ArrayList<neuron> outputLayer;
private ArrayList<Double> answers;
public net(Integer numInput, Integer numOut, ArrayList<Double> answers){
inputLayer = new ArrayList<neuron>();
outputLayer = new ArrayList<neuron>();
this.answers = answers;
for(int i=0; i<numOut; i++){
outputLayer.add(new neuron(true));
}
for(int i=0; i<numInput; i++){
ArrayList<Double> randomWeights = createRandomWeights(numInput);
inputLayer.add(new neuron(outputLayer, randomWeights, -100.00, true));
}
for(int i=0; i<numOut; i++){
outputLayer.get(i).setBackConn(inputLayer);
}
}
public ArrayList<neuron> getOutputs(){
return outputLayer;
}
public void backpropagation(){
for(int i=0; i<answers.size(); i++){
neuron iOut = outputLayer.get(i);
ArrayList<neuron> iOutBack = iOut.getBackConn();
Double iSigDeriv = (1-iOut.getOutput())*iOut.getOutput();
Double iError = (answers.get(i) - iOut.getOutput());
System.out.println("Answer: "+answers.get(i) + " iOut: "+iOut.getOutput()+" Error: "+iError+" Sigmoid: "+iSigDeriv);
for(int j=0; j<iOutBack.size(); j++){
neuron jNeuron = iOutBack.get(j);
Double ijWeight = jNeuron.getWeight(i);
System.out.println("ijWeight: "+ijWeight);
System.out.println("jNeuronOut: "+jNeuron.getOutput());
jNeuron.setWeight(i, ijWeight+(iSigDeriv*iError*jNeuron.getOutput()));
}
}
for(int i=0; i<inputLayer.size(); i++){
inputLayer.get(i).resetInput();
inputLayer.get(i).resetOutput();
}
}
public ArrayList<Double> createRandomWeights(Integer size){
ArrayList<Double> iWeight = new ArrayList<Double>();
for(int i=0; i<size; i++){
Double randNum = (2*Math.random())-1;
iWeight.add(randNum);
}
return iWeight;
}
public void setInputs(Double[] is){
for(int i=0; i<is.length; i++){
inputLayer.get(i).setInput(is[i]);
}
for(int i=0; i<outputLayer.size(); i++){
outputLayer.get(i).resetInput();
}
}
public void start(){
for(int i=0; i<inputLayer.size(); i++){
inputLayer.get(i).fire();
}
}
public void printOutput(){
for(int i=0; i<outputLayer.size(); i++){
System.out.println(outputLayer.get(i).getOutput().toString());
}
}
}
package myneuralnet;
import java.util.ArrayList;
public class neuron {
private ArrayList<neuron> connections;
private ArrayList<neuron> backconns;
private ArrayList<Double> weights;
private Double threshold;
private Double input;
private Boolean isOutput = false;
private Boolean isInput = false;
private Double totalSignal;
private Integer numCalled;
private Double myOutput;
public neuron(ArrayList<neuron> conns, ArrayList<Double> weights, Double threshold){
this.connections = conns;
this.weights = weights;
this.threshold = threshold;
this.totalSignal = 0.00;
this.numCalled = 0;
this.backconns = new ArrayList<neuron>();
this.input = 0.00;
}
public neuron(ArrayList<neuron> conns, ArrayList<Double> weights, Double threshold, Boolean isin){
this.connections = conns;
this.weights = weights;
this.threshold = threshold;
this.totalSignal = 0.00;
this.numCalled = 0;
this.backconns = new ArrayList<neuron>();
this.input = 0.00;
this.isInput = isin;
}
public neuron(Boolean tf){
this.connections = new ArrayList<neuron>();
this.weights = new ArrayList<Double>();
this.threshold = 0.00;
this.totalSignal = 0.00;
this.numCalled = 0;
this.isOutput = tf;
this.backconns = new ArrayList<neuron>();
this.input = 0.00;
}
public void setInput(Double input){
this.input = input;
}
public void setOut(Boolean tf){
this.isOutput = tf;
}
public void resetNumCalled(){
numCalled = 0;
}
public void setBackConn(ArrayList<neuron> backs){
this.backconns = backs;
}
public Double getOutput(){
return myOutput;
}
public Double getInput(){
return totalSignal;
}
public Double getRealInput(){
return input;
}
public ArrayList<Double> getWeights(){
return weights;
}
public ArrayList<neuron> getBackConn(){
return backconns;
}
public Double getWeight(Integer i){
return weights.get(i);
}
public void setWeight(Integer i, Double d){
weights.set(i, d);
}
public void setOutput(Double d){
myOutput = d;
}
public void activation(Double myInput){
numCalled++;
totalSignal += myInput;
if(numCalled==backconns.size() && isOutput){
System.out.println("Total Sig: "+totalSignal);
setInput(totalSignal);
setOutput(totalSignal);
}
}
public void activation(){
Double activationValue = 1 / (1 + Math.exp(input));
setInput(activationValue);
fire();
}
public void fire(){
for(int i=0; i<connections.size(); i++){
Double iWeight = weights.get(i);
neuron iConn = connections.get(i);
myOutput = (1/(1+(Math.exp(-input))))*iWeight;
iConn.activation(myOutput);
}
}
public void resetInput(){
input = 0.00;
totalSignal = 0.00;
}
public void resetOutput(){
myOutput = 0.00;
}
}
OK so that is a lot of code so allow me to explain. The net is simple for now, just an input layer and an output layer --- I want to add a hidden layer later but I'm taking baby steps for now. Each layer is an arraylist of neurons. Input neurons are loaded with inputs, a 1 and a 2 in this example. These neurons fire, which calculates the sigmoid of the inputs and outputs that to the output neurons, which adds them and stores the value. Then the net backpropagates by taking the (answer-output)(output)(1-output)(output of the specific input neuron) and updates the weights accordingly. A lot of times, it cycles through and I get infinity, which seems to correlate with negative weights or sigmoid. When that doesn't happen it converges to 1 and since (1-output of 1) is 0, my weights stop updating.
The numCalled and totalSignal values are just so the algorithm waits for all neuron inputs before continuing. I know I'm doing this an odd way, but the neuron class has an arraylist of neurons called connections to hold the neurons that it is forward connected to. Another arraylist called backconns holds the backward connections. I should be updating the correct weights as well since I am getting all back connections between neurons i and j but of all neurons j (the layer above i) I am only pulling weight i. I apologize for the messiness --- I've been trying lots of things for hours upon hours now and still cannot figure it out. Any help is greatly appreciated!
Some of the best textbooks on neural networks in general are Chris Bishop's and Simon Haykin's. Try reading through the chapter on backprop and understand why the terms in the weight update rule are the way they are.The reason why I am asking you to do that is that backprop is more subtle than it seems at first. Things change a bit if you use a linear activation function for the output layer (think about why you might want to do that. Hint: post-processing), or if you add a hidden layer. It got clearer for me when I actually read the book.
You might want to compare your code to this single layer perceptron.
I think you have a bug in your backprop algo. Also, try replacing the sigmoid with a squarewave.
http://web.archive.org/web/20101228185321/http://en.literateprograms.org/Perceptron_%28Java%29
what if my Output is 1 but my target is not?
The sigmoid function 1/(1 + Math.exp(-x)) never equates to 1. The lim as x approaches infinity is equal to 0, but this is a horizontal asymptote, so the function never actually touches 1. Therefore, if this expression is used to compute all of your output values, then your output will never be 1. So (1 - output) shouldn't ever equal 0.
I think your issue is during the calculation of the output. For a neural network, the output for each neuron is typically sigmoid(dot product of inputs and weights). In other words, value = input1 * weight1 + input2 * weight2 + ... (for each weight of neuron) + biasWeight. Then that neuron's output = 1 / (1 + Math.exp(-value). If it's calculated in this way, the output won't ever be equal to 1.