diff --git a/src/me/zombie_striker/neuralnetwork/NNAI.java b/src/me/zombie_striker/neuralnetwork/NNAI.java index a5fc8b2..91541b2 100644 --- a/src/me/zombie_striker/neuralnetwork/NNAI.java +++ b/src/me/zombie_striker/neuralnetwork/NNAI.java @@ -116,6 +116,11 @@ public static NNAI generateAI(NNBaseEntity nnEntityBase, public boolean[] think() { this.tick(); + for(Layer l : this.layers){ + for(Neuron n: l.neuronsInLayer){ + n.forceTriggerStengthUpdate(); + } + } boolean[] points = new boolean[getOutputNeurons().size()]; for (Neuron n : getOutputNeurons()) { if (n.isTriggered()) { @@ -189,6 +194,7 @@ public NNAI(Map map) { if (n != null) { n.setAI(this); addNeuron(n); + //getNeuronsInLayer(n.layer).add(n); } } } diff --git a/src/me/zombie_striker/neuralnetwork/NNBaseEntity.java b/src/me/zombie_striker/neuralnetwork/NNBaseEntity.java index 07725a0..ffafa4a 100644 --- a/src/me/zombie_striker/neuralnetwork/NNBaseEntity.java +++ b/src/me/zombie_striker/neuralnetwork/NNBaseEntity.java @@ -83,7 +83,6 @@ public void randomizeNeurons(){ } public boolean[] tickAndThink(){ - ai.tick(); return ai.think(); } diff --git a/src/me/zombie_striker/neuralnetwork/neurons/Neuron.java b/src/me/zombie_striker/neuralnetwork/neurons/Neuron.java index bbbb045..43dc488 100644 --- a/src/me/zombie_striker/neuralnetwork/neurons/Neuron.java +++ b/src/me/zombie_striker/neuralnetwork/neurons/Neuron.java @@ -62,7 +62,7 @@ public Neuron(NNAI ai, int layer) { } public boolean isTriggered() { - return getTriggeredStength() > threshold; + return getThreshold() < getTriggeredStength(); } /** diff --git a/src/me/zombie_striker/neuralnetwork/neurons/input/InputBlockNeuron.java b/src/me/zombie_striker/neuralnetwork/neurons/input/InputBlockNeuron.java index 0b0b1de..30e1e75 100644 --- a/src/me/zombie_striker/neuralnetwork/neurons/input/InputBlockNeuron.java +++ b/src/me/zombie_striker/neuralnetwork/neurons/input/InputBlockNeuron.java @@ -21,6 +21,11 @@ import me.zombie_striker.neuralnetwork.senses.Senses2D; import me.zombie_striker.neuralnetwork.senses.Sensory2D_Numbers; +/** + * DO NOT USE. Still updating! + * @author ZombieStriker + * + */ public class InputBlockNeuron extends InputNeuron { diff --git a/src/me/zombie_striker/neuralnetwork/neurons/input/InputLetterNeuron.java b/src/me/zombie_striker/neuralnetwork/neurons/input/InputLetterNeuron.java index 4692a65..bd9ef65 100644 --- a/src/me/zombie_striker/neuralnetwork/neurons/input/InputLetterNeuron.java +++ b/src/me/zombie_striker/neuralnetwork/neurons/input/InputLetterNeuron.java @@ -56,19 +56,16 @@ public static InputNeuron generateNeuronStatically(NNAI ai, int index, if(letters[index2]==letter) break; InputNeuron link = new InputLetterNeuron(ai, index, index2, sl); - // link.addNeuronData(ai); return link; } public static InputNeuron generateNeuronStatically(NNAI ai, int index, int letter, Sensory2D_Letters sl) { InputNeuron link = new InputLetterNeuron(ai, index, letter, sl); - // link.addNeuronData(ai); return link; } @Override public boolean isTriggered() { - //if (((Sensory2D_Letters) s).getWord().length() > xlink) if (((Sensory2D_Letters) s).getCharacterAt(xlink) == letter) return true; return false; @@ -76,7 +73,7 @@ public boolean isTriggered() { public InputLetterNeuron(Map map) { super(map); - this.letter=(char) map.get("char"); + this.letter= (map.get("char")+"").toCharArray()[0]; } @Override public Map serialize() { diff --git a/src/me/zombie_striker/neuralnetwork/neurons/input/InputMobNeuron.java b/src/me/zombie_striker/neuralnetwork/neurons/input/InputMobNeuron.java index 165a760..4412239 100644 --- a/src/me/zombie_striker/neuralnetwork/neurons/input/InputMobNeuron.java +++ b/src/me/zombie_striker/neuralnetwork/neurons/input/InputMobNeuron.java @@ -20,6 +20,11 @@ import me.zombie_striker.neuralnetwork.NNAI; import me.zombie_striker.neuralnetwork.senses.*; +/** + * DO NOT USE. Still updating! + * @author ZombieStriker + * + */ public class InputMobNeuron extends InputNeuron { public InputMobNeuron(NNAI ai,Sensory2D_Numbers sn) { diff --git a/src/me/zombie_striker/neuralnetwork/neurons/input/InputNeuron.java b/src/me/zombie_striker/neuralnetwork/neurons/input/InputNeuron.java index 3349852..ccd65b1 100644 --- a/src/me/zombie_striker/neuralnetwork/neurons/input/InputNeuron.java +++ b/src/me/zombie_striker/neuralnetwork/neurons/input/InputNeuron.java @@ -29,7 +29,7 @@ public class InputNeuron extends Neuron { public int ylink; public int zlink; - protected Senses s; + public Senses s; ///public Sensory_Vision entitiesVision; diff --git a/src/me/zombie_striker/neuralnetwork/neurons/input/InputNumberNeuron.java b/src/me/zombie_striker/neuralnetwork/neurons/input/InputNumberNeuron.java index 77a1eb2..9169022 100644 --- a/src/me/zombie_striker/neuralnetwork/neurons/input/InputNumberNeuron.java +++ b/src/me/zombie_striker/neuralnetwork/neurons/input/InputNumberNeuron.java @@ -17,6 +17,8 @@ along with this program. If not, see . **/ +import java.util.Map; + import me.zombie_striker.neuralnetwork.NNAI; import me.zombie_striker.neuralnetwork.senses.*; @@ -27,6 +29,10 @@ public InputNumberNeuron(NNAI ai, Sensory2D_Numbers sl) { this.s = sl; } + public InputNumberNeuron(Map map) { + super(map); + } + public InputNumberNeuron(NNAI ai, int row, int col, Sensory2D_Numbers sl) { super(ai, row, col,sl); diff --git a/src/me/zombie_striker/neuralnetwork/neurons/input/InputTickNeuron.java b/src/me/zombie_striker/neuralnetwork/neurons/input/InputTickNeuron.java index cdc975b..0d89d8d 100644 --- a/src/me/zombie_striker/neuralnetwork/neurons/input/InputTickNeuron.java +++ b/src/me/zombie_striker/neuralnetwork/neurons/input/InputTickNeuron.java @@ -20,6 +20,11 @@ import me.zombie_striker.neuralnetwork.NNAI; import me.zombie_striker.neuralnetwork.senses.*; +/** + * DO NOT USE. Still updating! + * @author ZombieStriker + * + */ public class InputTickNeuron extends InputNeuron { int maxTick=0; diff --git a/src/me/zombie_striker/neuralnetwork/senses/Sensory2D_Letters.java b/src/me/zombie_striker/neuralnetwork/senses/Sensory2D_Letters.java index f4d6e56..8f5198f 100644 --- a/src/me/zombie_striker/neuralnetwork/senses/Sensory2D_Letters.java +++ b/src/me/zombie_striker/neuralnetwork/senses/Sensory2D_Letters.java @@ -26,8 +26,8 @@ public class Sensory2D_Letters implements Senses2D{ private char[] letters= InputLetterNeuron.letters; - private String word; - private String fullWord; + private String word="null"; + private String fullWord="null"; public static final int MAX_LETTERS = 19; @Override @@ -49,7 +49,15 @@ public Sensory2D_Letters(String word) { } public char getCharacterAt(int index) { + if(fullWord==null)return ' '; + try{ return fullWord.charAt(index); + }catch(Exception e){ + /** + * Seriously, I have tried doing a length check, a null check. Do I seriously need to add a catch statement?> + */ + return ' '; + } } public String getWord(){ return word; @@ -64,8 +72,6 @@ public void changeWord(String word) { fullWord = sb.toString(); } public Sensory2D_Letters(Map map) { - word = null; - fullWord=null; } @Override diff --git a/src/me/zombie_striker/neuralnetwork/util/DeepReinforcementUtil.java b/src/me/zombie_striker/neuralnetwork/util/DeepReinforcementUtil.java index 42f8a66..3e3d319 100644 --- a/src/me/zombie_striker/neuralnetwork/util/DeepReinforcementUtil.java +++ b/src/me/zombie_striker/neuralnetwork/util/DeepReinforcementUtil.java @@ -40,6 +40,28 @@ public class DeepReinforcementUtil { */ public static void instantaneousReinforce(NNBaseEntity base, Neuron[] neuronsThatShouldBeTrue, int repetitions) { + instantaneousReinforce(base, neuronsThatShouldBeTrue, repetitions, 0); + } + + /** + * Teaches the NN for an instantaneous, constant answer regarding a single + * response. Useful for true-false situations + * + * @param Base + * The NeuralEntity + * @param neuronsThatShouldBeTrue + * Array of all neuons that should be equal to 1. The rest will + * try to be decreased to -1; + * @param repetitions + * the amount of repetitions for the training. + * @param chanceForSkip + * The chance that a neuron will be skipped. This is done to make + * sure neurons are not over specialized for each time the NN is + * reinforced. + */ + public static void instantaneousReinforce(NNBaseEntity base, + Neuron[] neuronsThatShouldBeTrue, int repetitions, + double chanceForSkip) { HashMap h = new HashMap<>(); for (Neuron n : base.ai.getOutputNeurons()) { boolean isRightNeuron = false; @@ -51,7 +73,7 @@ public static void instantaneousReinforce(NNBaseEntity base, } h.put(n, isRightNeuron ? 1.0 : -1.0); } - instantaneousReinforce(base, h, repetitions); + instantaneousReinforce(base, h, repetitions, chanceForSkip); } /** @@ -68,72 +90,93 @@ public static void instantaneousReinforce(NNBaseEntity base, */ public static void instantaneousReinforce(NNBaseEntity base, HashMap correctValues, int repetitions) { + instantaneousReinforce(base, correctValues, repetitions, 0); + } + + /** + * Teaches the NN for an instantaneous, constant answer regarding a single + * response. Useful for true-false situations + * + * @param Base + * the NeuralEntity + * @param correctValues + * a Hashmap of all neurons and the values they should be equal + * to + * @param repetitions + * the amount of repetitions for the training. + * @param chanceForSkip + * The chance that a neuron will be skipped. This is done to make + * sure neurons are not over specialized for each time the NN is + * reinforced. + * + */ + public static void instantaneousReinforce(NNBaseEntity base, + HashMap correctValues, int repetitions, + double chanceForSkip) { final double step = 0.01; for (int loops = 0; loops < repetitions; loops++) { HashMap suggestedValueForNeuron = correctValues; // Subtract -1 a second time to not get the outputs - //for (int layer = base.ai.MAX_LAYERS - 1 - 1; layer >= 0; layer--) { - for (int layer = 0;layer = 0; layer--) + // { + for (int layer = 0; layer < base.ai.MAX_LAYERS - 1; layer++) { + HashMap lastOutputs = new HashMap(); + // Since no new outputs are created, nor are any destroyed, we + // do not need to clear it: simply adding new values will + // override the existing vals. for (Neuron n : base.ai.getNeuronsInLayer(layer)) { - - - //Do thresh checks before if is not triggerred + if (Math.random() < chanceForSkip) + continue; + + // Do thresh checks before if is not triggered // Do thresholds after everything else if (!n.isTriggered()) { double orgThr = n.getThreshold(); - HashMap currentValsThre = new HashMap<>(); - for (Neuron outputs : suggestedValueForNeuron.keySet()) { - currentValsThre.put(outputs, + for (Neuron outputs : suggestedValueForNeuron.keySet()) + lastOutputs.put(outputs, outputs.getTriggeredStength()); - } - - if (!(n instanceof InputNeuron)) - if (n.getTriggeredStength() <= n.getThreshold()) { - n.setThreshold(-2); - n.forceTriggerUpdateTree(); - double shouldLowerVal = 0; - for (Entry c : currentValsThre - .entrySet()) { - double sug = suggestedValueForNeuron.get(c - .getKey()); - shouldLowerVal += (Math.abs(c.getValue() - - sug) - Math.abs(c.getKey() - .getTriggeredStength() - sug)); - } - n.setThreshold(orgThr); - if (shouldLowerVal > 0) { - n.setThreshold(removeExtremes(n.getThreshold() - step)); - } + + if (!(n instanceof InputNeuron) + && n.getTriggeredStength() <= n.getThreshold()) { + n.setThreshold(-2); + n.forceTriggerUpdateTree(); + double shouldLowerVal = 0; + for (Entry c : lastOutputs + .entrySet()) { + double sug = suggestedValueForNeuron.get(c + .getKey()); + shouldLowerVal += (Math.abs(c.getValue() - sug) - Math + .abs(c.getKey().getTriggeredStength() + - sug)); + } + n.setThreshold(orgThr); + if (shouldLowerVal > 0) { + n.setThreshold(removeExtremes(n.getThreshold() + - step)); } + } continue; } - - - - - - HashMap currentVals2 = new HashMap<>(); - for (Neuron outputs : suggestedValueForNeuron.keySet()) { - currentVals2 - .put(outputs, outputs.getTriggeredStength()); - } - n.setWeight(n.getWeight() - (step)); + + for (Neuron outputs : suggestedValueForNeuron.keySet()) + lastOutputs.put(outputs, outputs.getTriggeredStength()); + + n.setWeight(n.getWeight() - step); n.forceTriggerUpdateTree(); double change2 = 0.0; - for (Entry c : currentVals2.entrySet()) { + for (Entry c : lastOutputs.entrySet()) { // TODO: Multipled by 100 so the change is not a small // number. - int wasRightDirection = (Math - .abs((suggestedValueForNeuron.get(c.getKey()) - c - .getKey().getTriggeredStength())) <= Math - .abs(suggestedValueForNeuron.get(c.getKey()) - - c.getValue()) ? 1 : -1); + double sug = suggestedValueForNeuron.get(c.getKey()); + int wasRightDirection = Math.abs(sug + - c.getKey().getTriggeredStength()) <= Math + .abs(sug - c.getValue()) ? 1 : -1; change2 += wasRightDirection - * (Math.abs((c.getKey().getTriggeredStength() * 100) - - (c.getValue() * 100))); + * Math.abs(c.getKey().getTriggeredStength() + - c.getValue()); /* * change2 += ((Math * .abs((c.getKey().getTriggeredStength() * 100) - @@ -147,7 +190,7 @@ public static void instantaneousReinforce(NNBaseEntity base, } if (change2 == 0.0) { - n.setWeight(n.getWeight() + (step)); + n.setWeight(n.getWeight() + step); } else if (change2 < 0.0) { n.setWeight(n.getWeight() + (step * 2)); } @@ -158,29 +201,26 @@ public static void instantaneousReinforce(NNBaseEntity base, Neuron outputNeuronInstance = n.getAI() .getNeuronFromId(outputNeuronId); - HashMap currentVals = new HashMap<>(); - for (Neuron outputs : suggestedValueForNeuron.keySet()) { - currentVals.put(outputs, + for (Neuron outputs : suggestedValueForNeuron.keySet()) + lastOutputs.put(outputs, outputs.getTriggeredStength()); - } + n.setStrengthForNeuron(outputNeuronInstance, n.getOutputForNeuron(outputNeuronInstance) - - (step)); + - step); n.forceTriggerStengthUpdate(); outputNeuronInstance.forceTriggerUpdateTree(); double change = 0.0; - for (Entry c : currentVals.entrySet()) { - int wasRightDirection = (Math - .abs((suggestedValueForNeuron.get(c - .getKey()) - c.getKey() - .getTriggeredStength())) <= Math - .abs(suggestedValueForNeuron.get(c.getKey()) - - c.getValue()) ? 1 : -1); + for (Entry c : lastOutputs.entrySet()) { + double sug = suggestedValueForNeuron + .get(c.getKey()); + int wasRightDirection = (Math.abs(sug + - c.getKey().getTriggeredStength()) <= Math + .abs(sug - c.getValue()) ? 1 : -1); change += wasRightDirection - * (Math.abs((c.getKey() - .getTriggeredStength() * 100) - - (c.getValue() * 100))); + * Math.abs(c.getKey().getTriggeredStength() + - c.getValue()); /* * change += ((Math.abs((c.getKey() * .getTriggeredStength() * 100) - (c.getValue() * @@ -208,70 +248,59 @@ public static void instantaneousReinforce(NNBaseEntity base, n.forceTriggerStengthUpdate(); outputNeuronInstance.forceTriggerUpdateTree(); } - - - //Do check for inherit bias of neuron - HashMap currentVals3 = new HashMap<>(); - for (Neuron outputs : suggestedValueForNeuron.keySet()) { - currentVals3 - .put(outputs, outputs.getTriggeredStength()); - } - n.setBias(n.getBias()-step); + + // Do check for inherit bias of neuron + for (Neuron outputs : suggestedValueForNeuron.keySet()) + lastOutputs.put(outputs, outputs.getTriggeredStength()); + n.setBias(n.getBias() - step); n.forceTriggerUpdateTree(); double change3 = 0.0; - for (Entry c : currentVals3.entrySet()) { + for (Entry c : lastOutputs.entrySet()) { // TODO: Multipled by 100 so the change is not a small // number. - int wasRightDirection = (Math - .abs((suggestedValueForNeuron.get(c.getKey()) - c - .getKey().getTriggeredStength())) <= Math - .abs(suggestedValueForNeuron.get(c.getKey()) - - c.getValue()) ? 1 : -1); + double sug = suggestedValueForNeuron.get(c.getKey()); + int wasRightDirection = Math.abs(sug + - c.getKey().getTriggeredStength()) <= Math + .abs(sug - c.getValue()) ? 1 : -1; change2 += wasRightDirection - * (Math.abs((c.getKey().getTriggeredStength() * 100) - - (c.getValue() * 100))); + * Math.abs(c.getKey().getTriggeredStength() + - c.getValue()); } - //Step > 0 is already accounted for, since we already deceased the step + // Step > 0 is already accounted for, since we already + // deceased the step if (change3 == 0.0) { - n.setBias(n.getBias()+step); + n.setBias(n.getBias() + step); } else if (change3 < 0.0) { - n.setBias(n.getBias()+(step*2)); + n.setBias(n.getBias() + (step * 2)); } - n.setBias(removeExtremes(n.getBias(),50)); + n.setBias(removeExtremes(n.getBias(), 50)); n.forceTriggerUpdateTree(); - - - - //Do Thresh checks after everything else if is triggered - if (!(n instanceof InputNeuron)) - if (n.getTriggeredStength() > n.getThreshold()) { - double orgThr = n.getThreshold(); - HashMap currentValsThre = new HashMap<>(); - for (Neuron outputs : suggestedValueForNeuron.keySet()) { - currentValsThre.put(outputs, - outputs.getTriggeredStength()); - } - - n.setThreshold(2); - n.forceTriggerUpdateTree(); - double shouldIncreaseVal = 0; - for (Entry c : currentValsThre - .entrySet()) { - double sug = suggestedValueForNeuron.get(c - .getKey()); - shouldIncreaseVal += (Math.abs(c.getValue() - - sug) - Math.abs(c.getKey() - .getTriggeredStength() - sug)); - } - n.setThreshold(orgThr); - if (shouldIncreaseVal > 0) { - n.setThreshold(removeExtremes(n.getThreshold() + step)); - } - } + + // Do Thresh checks after everything else if is triggered + if (!(n instanceof InputNeuron) + && n.getThreshold() < n.getTriggeredStength()) { + double orgThr = n.getThreshold(); + for (Neuron outputs : suggestedValueForNeuron.keySet()) + lastOutputs.put(outputs, + outputs.getTriggeredStength()); + + n.setThreshold(2); + n.forceTriggerUpdateTree(); + double shouldIncreaseVal = 0; + for (Entry c : lastOutputs.entrySet()) { + double sug = suggestedValueForNeuron + .get(c.getKey()); + shouldIncreaseVal += (Math.abs(c.getValue() - sug) - Math + .abs(c.getKey().getTriggeredStength() - sug)); + } + n.setThreshold(orgThr); + if (shouldIncreaseVal > 0) + n.setThreshold(removeExtremes(n.getThreshold() + + step)); } - + } } } } @@ -283,6 +312,7 @@ private static double removeExtremes(double d) { return -1; return d; } + private static double removeExtremes(double d, double max) { if (d > max) return max; diff --git a/src/me/zombie_striker/nnmain/Main.java b/src/me/zombie_striker/nnmain/Main.java index ba03939..bc61620 100644 --- a/src/me/zombie_striker/nnmain/Main.java +++ b/src/me/zombie_striker/nnmain/Main.java @@ -100,6 +100,8 @@ public void onLoad() { protected static Main plugin; + protected boolean enableMetrics = true; + @Override public void onDisable() { plugin = null; @@ -133,6 +135,12 @@ public void onEnable() { Bukkit.getPluginManager().registerEvents( new ExampleSwearListener(getNn()), this); + if (!getConfig().contains("enableStats")) { + getConfig().set("enableStats", true); + saveConfig(); + } + enableMetrics = getConfig().getBoolean("enableStats"); + new Updater(this, 280241); /** * Everyone should want the most up to date version of the plugin, so @@ -141,14 +149,22 @@ public void onEnable() { * anything, and even if I did, I would deprecate the methods for a long * period of time before I do, nothing should really break. */ - - Metrics metrics = new Metrics(this); - /** - * I use bStats metrics to monitor how many servers are using my API. - * This does not send any personal/private information (this only sends - * the server version, Java version, the plugin's version, and system - * architecture) - */ + if (enableMetrics) { + /** + * I use bStats metrics to monitor how many servers are using my + * API. This does not send any personal/private information. This + * only sends: + * + * the server version, Java version, + * the plugin's version, + * system architecture, + * Core count, + * + * You can view the stats being collected at: + * https://bstats.org/plugin/bukkit/NeuralNetworkAPI + */ + Metrics metrics = new Metrics(this); + } } public static Main getMainClass() {