TicTacToe - NueralNet

NueralNet.java

import java.util.Random;
import java.util.Vector;
import java.io.*;

public class NueralNet implements Serializable {
    protected Random rand;

    protected double m_OutputLayer;
    protected double[] m_InputLayer;
    protected double[] m_HiddenLayerOutputs;
    protected double[] m_HiddenLayerWeights;
    protected double[] m_OutputLayerWeights;
    protected double[] m_Sigma;
    protected double m_LastOutput;
    protected Vector m_Grads;
    protected int m_InputNum = 3;
    protected int m_NueronsNum = 3;
    protected int m_t;
    protected int m_TimePeriod = 10;
    protected double m_alpha = 0.1; // learning parameter 
    protected double[] m_LambdaPower;
    protected double m_Lambda = 0.1;
    protected double m_AlphaChangeRatio = 0.998;

    private void initNet() {
        prepareLambdaPower();
        rand = new Random(System.currentTimeMillis());
        m_OutputLayer = 0;
        m_InputLayer = new double[m_InputNum];
        m_HiddenLayerOutputs = new double[m_NueronsNum];
        m_HiddenLayerWeights = new double[m_NueronsNum * m_InputNum];
        m_OutputLayerWeights = new double[m_NueronsNum];
        m_Sigma = new double[m_NueronsNum];
        initWeights();
        m_t = 1;
        m_Grads = new Vector();
    }
    public NueralNet() {
        initNet();
    }
public NueralNet(int InputSize, int HiddenLayerSize) {
    m_InputNum = InputSize;
    m_NueronsNum = HiddenLayerSize;
    initNet();
}
    // compute the delta weights vector
    private void computeDeltaW(double reward, double Yt1, double Yt) {
        int i;
        int j;
        int k;
        double sigma = 0;
        double[] Grad;

        double dY;

        dY = m_alpha * (reward + Yt1 - Yt);

        // compute the delta for output layer weights

        for (i = 0; i < m_NueronsNum; i++) {
            if (m_Lambda > 0) {
                sigma = 0;
                for (k = 1; k <= m_t - 1; k++) {
                    Grad = (double[]) m_Grads.elementAt(k - 1);
                    sigma += m_LambdaPower[(m_t - 1) - k] * Grad[i];
                }
                m_OutputLayerWeights[i] += dY * sigma;
            } else {
                Grad = (double[]) m_Grads.elementAt((m_t - 1) - 1);
                m_OutputLayerWeights[i] += dY * Grad[i];
            }
        }
        for (i = 0; i < m_NueronsNum; i++) {
            for (j = 0; j < m_InputNum; j++) {
                if (m_Lambda > 0) {
                    sigma = 0;
                    for (k = 1; k <= m_t - 1; k++) {
                        Grad = ((double[]) m_Grads.elementAt(k - 1));
                        sigma += m_LambdaPower[(m_t - 1) - k] * Grad[i * m_InputNum + j + m_NueronsNum];
                    }
                    m_HiddenLayerWeights[i * m_InputNum + j] += sigma * dY;
                } else {
                    Grad = (double[]) m_Grads.elementAt((m_t - 1) - 1);
                    m_HiddenLayerWeights[i * m_InputNum
                        + j] += dY * Grad[i * m_InputNum
                        + j
                        + m_NueronsNum];
                }
            }
        }
    }
    private double[] computeGrad() {
        int i;
        int j;
        int sigma = 0;
        double[] Grad = new double[m_NueronsNum * m_InputNum + m_NueronsNum];

        for (i = 0; i < m_NueronsNum; i++) {
            Grad[i] = m_HiddenLayerOutputs[i] / m_NueronsNum;
        }

        for (i = 0; i < m_NueronsNum; i++) {
            for (j = 0; j < m_InputNum; j++) {
                Grad[i * m_InputNum + j + m_NueronsNum] =
                    dTangh(m_Sigma[i])
                        * m_OutputLayerWeights[i]
                        * m_InputLayer[j]
                        / (m_NueronsNum * m_InputNum);
            }
        }
        return Grad;
    }

    private void computeHiddenOutputs() {
        double sigma = 0;
        int i;
        int j;

        for (i = 0; i < m_NueronsNum; i++) {
            sigma = 0;
            for (j = 0; j < m_InputNum; j++) {
                sigma += m_HiddenLayerWeights[i * m_InputNum + j] * m_InputLayer[j];
            }
            m_Sigma[i] = sigma / m_InputNum;
            m_HiddenLayerOutputs[i] = tangh(sigma);
        }
    }
    // compute output for every layer in the net, including the final output
    private void computeNetOutput() {
        int i;
        double sigma = 0;

        for (i = 0; i < m_NueronsNum; i++) {
            sigma += m_OutputLayerWeights[i] * m_HiddenLayerOutputs[i];
        }
        m_OutputLayer = sigma / m_NueronsNum;
    }
    private double dTangh(double x) {
        double exp = Math.exp(x);
        double mexp = Math.exp(-x);
        double Ret = 4.0 / ((exp + mexp) * (exp + mexp));
        return Ret;
    }
    public void finishUpdateWeights(double Score) {
        computeDeltaW(Score, 0.0, m_OutputLayer);
  finishUpdateWeights();
    }
 public void finishUpdateWeights() {
        m_t = 1;
        m_alpha = m_alpha * m_AlphaChangeRatio;
        initOutputs();
    }
    /**
     * Insert the method's description here.
     * Creation date: (9/22/2001 11:58:28 AM)
     * @return double
     */
    public double getAlphaChangeRatio() {
        return m_AlphaChangeRatio;
    }
    public int getHiddenLayerSize() {
        return m_NueronsNum;
    }
    /**
     * Insert the method's description here.
     * Creation date: (9/22/2001 2:30:06 PM)
     * @return double
     */
    public double getLambda() {
        return m_Lambda;
    }
    public double getScore(double[] Input) {
        initInputLayer(Input);
        computeHiddenOutputs();
        computeNetOutput();
        return m_OutputLayer;
    }
    /**
     * Insert the method's description here.
     * Creation date: (9/22/2001 2:32:17 PM)
     * @return double
     */
    public double getAlpha() {
        return m_alpha;
    }
    // initialized input layer 
    private void initInputLayer(double[] Arr) {
        System.arraycopy(Arr, 0, m_InputLayer, 0, m_InputNum);
    }
    // initialized weights
    private void initWeights() {
        for (int i = 0; i < m_NueronsNum; i++) {
            m_OutputLayerWeights[i] = rand.nextDouble() * 2 - 1;
        }
        for (int i = 0; i < m_InputNum * m_NueronsNum; i++) {
            m_HiddenLayerWeights[i] = rand.nextDouble() * 2 - 1;
        }
    }
    public static NueralNet loadNet(String FileName) {
        NueralNet Net = null;

        if (FileName != null) {
            try {
                ObjectInputStream in = new ObjectInputStream(new FileInputStream(FileName));
                Net = new NueralNet();

                Net.m_OutputLayer = in.readDouble();
                Net.m_InputLayer = (double[]) in.readObject();
                Net.m_HiddenLayerOutputs = (double[]) in.readObject();
                Net.m_HiddenLayerWeights = (double[]) in.readObject();
                Net.m_OutputLayerWeights = (double[]) in.readObject();
                Net.m_Sigma = (double[]) in.readObject();
                Net.m_LastOutput = in.readDouble();
                Net.m_Grads = (Vector) in.readObject();
                Net.m_InputNum = in.readInt();
                Net.m_NueronsNum = in.readInt();
                Net.m_t = in.readInt();
                Net.m_TimePeriod = in.readInt();
                Net.m_alpha = in.readDouble();
                Net.m_LambdaPower = (double[]) in.readObject();
                Net.m_Lambda = in.readDouble();
                Net.m_AlphaChangeRatio = in.readDouble();
                in.close();
            } catch (Exception E) {
    Net = null;
            }
        }
        return Net;
    }
    private void prepareLambdaPower() {
        m_LambdaPower = new double[m_TimePeriod];
        int i;

        for (i = 0; i < m_TimePeriod; i++) {
            m_LambdaPower[i] = Math.pow(m_Lambda, i);
        }
    }

    public void saveNet(String FileName) {
        if (FileName != null) {
            try {
                ObjectOutputStream out =
                    new ObjectOutputStream(new FileOutputStream(FileName, false));
                out.writeDouble(m_OutputLayer);
                out.writeObject(m_InputLayer);
                out.writeObject(m_HiddenLayerOutputs);
                out.writeObject(m_HiddenLayerWeights);
                out.writeObject(m_OutputLayerWeights);
                out.writeObject(m_Sigma);
                out.writeDouble(m_LastOutput);
                out.writeObject(m_Grads);
                out.writeInt(m_InputNum);
                out.writeInt(m_NueronsNum);
                out.writeInt(m_t);
                out.writeInt(m_TimePeriod);
                out.writeDouble(m_alpha);
                out.writeObject(m_LambdaPower);
                out.writeDouble(m_Lambda);
                out.writeDouble(m_AlphaChangeRatio);
                out.close();
            } catch (Exception E) {

            }
        }
    }
    // Saving Outputs for current network run
    private void saveOutputs() {
        m_LastOutput = m_OutputLayer;
        m_Grads.addElement(computeGrad());
    }

    private void initOutputs() {
        m_Grads.removeAllElements();
    }
    /**
     * Insert the method's description here.
     * Creation date: (9/22/2001 11:58:28 AM)
     * @param newAlphaChangeRatio double
     */
    public void setAlphaChangeRatio(double newAlphaChangeRatio) {
        m_AlphaChangeRatio = newAlphaChangeRatio;
    }

    public void setLambda(double newLambda) {
        m_Lambda = newLambda;
        prepareLambdaPower();
    }
    /**
     * Insert the method's description here.
     * Creation date: (9/22/2001 2:32:17 PM)
     * @param newStartAlpha double
     */
    public void setAlpha(double newStartAlpha) {
        m_alpha = newStartAlpha;
    }
    public void updateWeights(double reward, double[] Input) {
        getScore(Input);
        if (m_t > 1) {
            computeDeltaW(reward, m_OutputLayer, m_LastOutput);
        }
        getScore(Input);
        saveOutputs();
        m_t++;
    }
    private double tangh(double x) {
        double exp = Math.exp(x);
        double mexp = Math.exp(-x);
        double Ret = (exp - mexp) / (exp + mexp);
        return Ret;
    }
}

Related files:
TicTacToe.java
ANNPlayer.java
NueralNet.java
HumenPlayer.java
MessageBox.java
TurnDialog.java
Applet1.java

See also
Coin Toss Programming Simulator

Do you have a Java Problem?
Ask It in The Java Forum

Java Books
Java Certification, Programming, JavaBean and Object Oriented Reference Books

Return to : Java Programming Hints and Tips

All the site contents are Copyright © www.erpgreat.com and the content authors. All rights reserved.
All product names are trademarks of their respective companies.
The site www.erpgreat.com is not affiliated with or endorsed by any company listed at this site.
Every effort is made to ensure the content integrity.  Information used on this site is at your own risk.
 The content on this site may not be reproduced or redistributed without the express written permission of
www.erpgreat.com or the content authors.