For an assignment I'm supposed to test different types of recommenders, which I have to implement first. I've been looking around for a good library to do that (I had thought about Weka at first) and stumbled upon Mahout.
I must therefore put forward that: a) I'm completely new to Mahout b) I do not have a strong background in recommenders nor their algorithms (otherwise I wouldn't be doing this class...) and c) sorry but I'm far from being the best developper in the world ==> I'd appreciate if you could use layman terms (as far as possible...) :)
I've been following some tutorials (e.g. this, as well as part2) and got some preliminary results on item-based and user-based recommenders.
However, I'm not very happy with the item-based prediction. So far, I've only found similarity functions that do not take into consideration the users' rating-biases. I was wondering if there is something like adjusted cosine similarity. Any hints?
Here is a sample of the AdjustedCosineSimilarity I created. You must remember that this will be slower than PearsonCorrelationSimilarity because of the sqrt computations, but will produce better results. At least for my dataset results were much better. But you should make a trade off, quality/performance, and depending of your needs you should use the implementation you want.
/**
* Custom implementation of {#link AdjustedCosineSimilarity}
*
* #author dmilchevski
*
*/
public class AdjustedCosineSimilarity extends AbstractSimilarity {
/**
* Creates new {#link AdjustedCosineSimilarity}
*
* #param dataModel
* #throws TasteException
*/
public AdjustedCosineSimilarity(DataModel dataModel)
throws TasteException {
this(dataModel, Weighting.UNWEIGHTED);
}
/**
* Creates new {#link AdjustedCosineSimilarity}
*
* #param dataModel
* #param weighting
* #throws TasteException
*/
public AdjustedCosineSimilarity(DataModel dataModel, Weighting weighting)
throws TasteException {
super(dataModel, weighting, true);
Preconditions.checkArgument(dataModel.hasPreferenceValues(),
"DataModel doesn't have preference values");
}
/**
* Compute the result
*/
#Override
double computeResult(int n, double sumXY, double sumX2, double sumY2, double sumXYdiff2) {
if (n == 0) {
return Double.NaN;
}
// Note that sum of X and sum of Y don't appear here since they are
// assumed to be 0;
// the data is assumed to be centered.
double denominator = Math.sqrt(sumX2) * Math.sqrt(sumY2);
if (denominator == 0.0) {
// One or both parties has -all- the same ratings;
// can't really say much similarity under this measure
return Double.NaN;
}
return sumXY / denominator;
}
/**
* Gets the average preference
* #param prefs
* #return
*/
private double averagePreference(PreferenceArray prefs){
double sum = 0.0;
int n = prefs.length();
for(int i=0; i<n; i++){
sum+=prefs.getValue(i);
}
if(n>0){
return sum/n;
}
return 0.0d;
}
/**
* Compute the item similarity between two items
*/
#Override
public double itemSimilarity(long itemID1, long itemID2) throws TasteException {
DataModel dataModel = getDataModel();
PreferenceArray xPrefs = dataModel.getPreferencesForItem(itemID1);
PreferenceArray yPrefs = dataModel.getPreferencesForItem(itemID2);
int xLength = xPrefs.length();
int yLength = yPrefs.length();
if (xLength == 0 || yLength == 0) {
return Double.NaN;
}
long xIndex = xPrefs.getUserID(0);
long yIndex = yPrefs.getUserID(0);
int xPrefIndex = 0;
int yPrefIndex = 0;
double sumX = 0.0;
double sumX2 = 0.0;
double sumY = 0.0;
double sumY2 = 0.0;
double sumXY = 0.0;
double sumXYdiff2 = 0.0;
int count = 0;
// No, pref inferrers and transforms don't appy here. I think.
while (true) {
int compare = xIndex < yIndex ? -1 : xIndex > yIndex ? 1 : 0;
if (compare == 0) {
// Both users expressed a preference for the item
double x = xPrefs.getValue(xPrefIndex);
double y = yPrefs.getValue(yPrefIndex);
long xUserId = xPrefs.getUserID(xPrefIndex);
long yUserId = yPrefs.getUserID(yPrefIndex);
double xMean = averagePreference(dataModel.getPreferencesFromUser(xUserId));
double yMean = averagePreference(dataModel.getPreferencesFromUser(yUserId));
sumXY += (x - xMean) * (y - yMean);
sumX += x;
sumX2 += (x - xMean) * (x - xMean);
sumY += y;
sumY2 += (y - yMean) * (y - yMean);
double diff = x - y;
sumXYdiff2 += diff * diff;
count++;
}
if (compare <= 0) {
if (++xPrefIndex == xLength) {
break;
}
xIndex = xPrefs.getUserID(xPrefIndex);
}
if (compare >= 0) {
if (++yPrefIndex == yLength) {
break;
}
yIndex = yPrefs.getUserID(yPrefIndex);
}
}
double result;
// See comments above on these computations
double n = (double) count;
double meanX = sumX / n;
double meanY = sumY / n;
// double centeredSumXY = sumXY - meanY * sumX - meanX * sumY + n *
// meanX * meanY;
double centeredSumXY = sumXY - meanY * sumX;
// double centeredSumX2 = sumX2 - 2.0 * meanX * sumX + n * meanX *
// meanX;
double centeredSumX2 = sumX2 - meanX * sumX;
// double centeredSumY2 = sumY2 - 2.0 * meanY * sumY + n * meanY *
// meanY;
double centeredSumY2 = sumY2 - meanY * sumY;
// result = computeResult(count, centeredSumXY, centeredSumX2,
// centeredSumY2, sumXYdiff2);
result = computeResult(count, sumXY, sumX2, sumY2, sumXYdiff2);
if (!Double.isNaN(result)) {
result = normalizeWeightResult(result, count,
dataModel.getNumUsers());
}
return result;
}
}
Related
is supposed to calculate the coordinates of a projectile launched with respect to time (steps of 100ms), with a linear equation, and it outputs linear numbers, but if i plot this equation with CalcMe.com (math tool) it makes a parabolic plot
InVel = Double.parseDouble(jTextField1.getText());
g = Double.parseDouble(jTextField8.getText());
y = 1;
while(y >= -1) {
t += 100;
x = InVel * TimeUnit.MILLISECONDS.toSeconds(t) * Math.cos(45);
y = InVel * TimeUnit.MILLISECONDS.toSeconds(t) * Math.sin(45) - (1 / 2) * g * Math.pow(TimeUnit.MILLISECONDS.toSeconds(t), 2);
//System.out.print(Double.toString(x));
//System.out.printf(" ");
System.out.print(Double.toString(y));
System.out.printf("%n");
}
jTextField6.setText(Double.toString(x));
the code is in java
g is constant (9.8)
and invel is given by user so its constant too
g is the gravity and invel the initial velocity of the projectile
the equation is:x=invel*time*cos(45) and y=invel*time*sin(45)-(1/2)*g*t^2
anyone can help me?
Your milisecond to second value conversion method TimeUnit.MILLISECONDS.toSeconds(t) is the main fact. Its returning long value which one you are wanted double. Please take a look on below code. Probably its your answer. Just replace hard-coded value with your jTextField
public static void main(String[] args) {
double InVel = Double.parseDouble("10.555");
double g = Double.parseDouble("9.8");
double y = 1;
double x=0;
double t=0;
while(y >= -1) {
t += 100;
double timeInSeconds = (t / (double)1000) % (double)60;
x = InVel * timeInSeconds * Math.cos(45);
y = InVel * timeInSeconds * Math.sin(45) - ((double) 1 / (double) 2) * g * Math.pow(timeInSeconds, 2);
//System.out.print(Double.toString(x));
//System.out.printf(" ");
System.out.println("X = " + x + " Y = " + Double.toString(y));
System.out.printf("%n");
}
}
I have found Haralick's algorithm already implemented. It is used to get some feature with the help of Gray-Level Co-occurence matrices.
Now i have problems getting it to work. There are no exceptions. The code is fine. I'm not sure where to begin. Can someone help me with the first steps?How to i get a texture feature?
Below you can find the complete Haralick source code:
package de.lmu.dbs.jfeaturelib.features;
import Jama.Matrix;
import de.lmu.dbs.jfeaturelib.Progress;
import de.lmu.ifi.dbs.utilities.Arrays2;
import ij.plugin.filter.PlugInFilter;
import ij.process.ByteProcessor;
import ij.process.ImageProcessor;
import java.util.Arrays;
import java.util.EnumSet;
/**
* Haralick texture features
*
* http://makseq.com/materials/lib/Articles-Books/Filters/Texture/Co-occurence/haralick73.pdf
* <pre>
* #article{haralick1973textural,
* title={Textural features for image classification},
* author={Haralick, R.M. and Shanmugam, K. and Dinstein, I.},
* journal={Systems, Man and Cybernetics, IEEE Transactions on},
* volume={3},
* number={6},
* pages={610--621},
* year={1973},
* publisher={IEEE}
* }
* </pre>
*
* #author graf
*/
public class Haralick extends AbstractFeatureDescriptor {
/**
* The number of gray values for the textures
*/
private final int NUM_GRAY_VALUES = 32;
/**
* p_(x+y) statistics
*/
private double[] p_x_plus_y = new double[2 * NUM_GRAY_VALUES - 1];
/**
* p_(x-y) statistics
*/
private double[] p_x_minus_y = new double[NUM_GRAY_VALUES];
/**
* row mean value
*/
private double mu_x = 0;
/**
* column mean value
*/
private double mu_y = 0;
/**
* row variance
*/
private double var_x = 0;
/**
* column variance
*/
private double var_y = 0;
/**
* HXY1 statistics
*/
private double hx = 0;
/**
* HXY2 statistics
*/
private double hy = 0;
/**
* HXY1 statistics
*/
private double hxy1 = 0;
/**
* HXY2 statistics
*/
private double hxy2 = 0;
/**
* p_x statistics
*/
private double[] p_x = new double[NUM_GRAY_VALUES];
/**
* p_y statistics
*/
private double[] p_y = new double[NUM_GRAY_VALUES];
// -
private int haralickDist;
double[] features = null;
/**
* Constructs a haralick detector with default parameters.
*/
public Haralick() {
this.haralickDist = 1;
}
/**
* Constructs a haralick detector.
*
* #param haralickDist Integer for haralick distribution
*/
public Haralick(int haralickDist) {
this.haralickDist = haralickDist;
}
/**
* Defines the capability of the algorithm.
*
* #see PlugInFilter
* #see #supports()
*/
#Override
public EnumSet<Supports> supports() {
EnumSet set = EnumSet.of(
Supports.NoChanges,
Supports.DOES_8C,
Supports.DOES_8G,
Supports.DOES_RGB);
return set;
}
/**
* Starts the haralick detection.
*
* #param ip ImageProcessor of the source image
*/
#Override
public void run(ImageProcessor ip) {
if (!ByteProcessor.class.isAssignableFrom(ip.getClass())) {
ip = ip.convertToByte(true);
}
firePropertyChange(Progress.START);
process((ByteProcessor) ip);
addData(features);
firePropertyChange(Progress.END);
}
/**
* Returns information about the getFeature
*/
#Override
public String getDescription() {
StringBuilder sb = new StringBuilder();
sb.append("Haralick features: ");
sb.append("Angular 2nd moment, ");
sb.append("Contrast, ");
sb.append("Correlation, ");
sb.append("variance, ");
sb.append("Inverse Difference Moment, ");
sb.append("Sum Average, ");
sb.append("Sum Variance, ");
sb.append("Sum Entropy, ");
sb.append("Entropy, ");
sb.append("Difference Variance, ");
sb.append("Difference Entropy, ");
sb.append("Information Measures of Correlation, ");
sb.append("Information Measures of Correlation, ");
sb.append("Maximum Correlation COefficient");
return sb.toString();
}
private void process(ByteProcessor image) {
features = new double[14];
firePropertyChange(new Progress(1, "creating coocurrence matrix"));
Coocurrence coocurrence = new Coocurrence(image, NUM_GRAY_VALUES, this.haralickDist);
double[][] cooccurrenceMatrix = coocurrence.getCooccurrenceMatrix();
double meanGrayValue = coocurrence.getMeanGrayValue();
firePropertyChange(new Progress(25, "normalizing"));
normalize(cooccurrenceMatrix, coocurrence.getCooccurenceSums());
firePropertyChange(new Progress(50, "computing statistics"));
calculateStatistics(cooccurrenceMatrix);
firePropertyChange(new Progress(75, "computing features"));
double[][] p = cooccurrenceMatrix;
double[][] Q = new double[NUM_GRAY_VALUES][NUM_GRAY_VALUES];
for (int i = 0; i < NUM_GRAY_VALUES; i++) {
double sum_j_p_x_minus_y = 0;
for (int j = 0; j < NUM_GRAY_VALUES; j++) {
double p_ij = p[i][j];
sum_j_p_x_minus_y += j * p_x_minus_y[j];
features[0] += p_ij * p_ij;
features[2] += i * j * p_ij - mu_x * mu_y;
features[3] += (i - meanGrayValue) * (i - meanGrayValue) * p_ij;
features[4] += p_ij / (1 + (i - j) * (i - j));
features[8] += p_ij * log(p_ij);
// feature 13
if (p_ij != 0 && p_x[i] != 0) { // would result in 0
for (int k = 0; k < NUM_GRAY_VALUES; k++) {
if (p_y[k] != 0 && p[j][k] != 0) { // would result in NaN
Q[i][j] += (p_ij * p[j][k]) / (p_x[i] * p_y[k]);
}
}
}
}
features[1] += i * i * p_x_minus_y[i];
features[9] += (i - sum_j_p_x_minus_y) * (i - sum_j_p_x_minus_y) * p_x_minus_y[i];
features[10] += p_x_minus_y[i] * log(p_x_minus_y[i]);
}
// feature 13: Max Correlation Coefficient
double[] realEigenvaluesOfQ = new Matrix(Q).eig().getRealEigenvalues();
Arrays2.abs(realEigenvaluesOfQ);
Arrays.sort(realEigenvaluesOfQ);
features[13] = Math.sqrt(realEigenvaluesOfQ[realEigenvaluesOfQ.length - 2]);
features[2] /= Math.sqrt(var_x * var_y);
features[8] *= -1;
features[10] *= -1;
double maxhxhy = Math.max(hx, hy);
if (Math.signum(maxhxhy) == 0) {
features[11] = 0;
} else {
features[11] = (features[8] - hxy1) / maxhxhy;
}
features[12] = Math.sqrt(1 - Math.exp(-2 * (hxy2 - features[8])));
for (int i = 0; i < 2 * NUM_GRAY_VALUES - 1; i++) {
features[5] += i * p_x_plus_y[i];
features[7] += p_x_plus_y[i] * log(p_x_plus_y[i]);
double sum_j_p_x_plus_y = 0;
for (int j = 0; j < 2 * NUM_GRAY_VALUES - 1; j++) {
sum_j_p_x_plus_y += j * p_x_plus_y[j];
}
features[6] += (i - sum_j_p_x_plus_y) * (i - sum_j_p_x_plus_y) * p_x_plus_y[i];
}
features[7] *= -1;
}
/**
* Calculates the statistical properties.
*/
private void calculateStatistics(double[][] cooccurrenceMatrix) {
// p_x, p_y, p_x+y, p_x-y
for (int i = 0; i < NUM_GRAY_VALUES; i++) {
for (int j = 0; j < NUM_GRAY_VALUES; j++) {
double p_ij = cooccurrenceMatrix[i][j];
p_x[i] += p_ij;
p_y[j] += p_ij;
p_x_plus_y[i + j] += p_ij;
p_x_minus_y[Math.abs(i - j)] += p_ij;
}
}
// mean and variance values
double[] meanVar;
meanVar = meanVar(p_x);
mu_x = meanVar[0];
var_x = meanVar[1];
meanVar = meanVar(p_y);
mu_y = meanVar[0];
var_y = meanVar[1];
for (int i = 0; i < NUM_GRAY_VALUES; i++) {
// hx and hy
hx += p_x[i] * log(p_x[i]);
hy += p_y[i] * log(p_y[i]);
// hxy1 and hxy2
for (int j = 0; j < NUM_GRAY_VALUES; j++) {
double p_ij = cooccurrenceMatrix[i][j];
hxy1 += p_ij * log(p_x[i] * p_y[j]);
hxy2 += p_x[i] * p_y[j] * log(p_x[i] * p_y[j]);
}
}
hx *= -1;
hy *= -1;
hxy1 *= -1;
hxy2 *= -1;
}
/**
* Compute mean and variance of the given array
*
* #param a inut values
* #return array{mean, variance}
*/
private double[] meanVar(double[] a) {
// VAR(X) = E(X^2) - E(X)^2
double ex = 0, ex2 = 0; // E(X), E(X^2)
for (int i = 0; i < NUM_GRAY_VALUES; i++) {
ex += a[i];
ex2 += a[i] * a[i];
}
ex /= a.length;
ex2 /= a.length;
double var = ex2 - ex * ex;
return new double[]{ex, var};
}
/**
* Returns the logarithm of the specified value.
*
* #param value the value for which the logarithm should be returned
* #return the logarithm of the specified value
*/
private double log(double value) {
double log = Math.log(value);
if (log == Double.NEGATIVE_INFINITY) {
log = 0;
}
return log;
}
private void normalize(double[][] A, double sum) {
for (int i = 0; i < A.length; i++) {
Arrays2.div(A[i], sum);
}
}
//<editor-fold defaultstate="collapsed" desc="getter/Setter">
/**
* Getter for haralick distributions
*
* #return haralick distributions
*/
public int getHaralickDist() {
return haralickDist;
}
/**
* Setter for haralick distributions
*
* #param haralickDist int for haralick distributions
*/
public void setHaralickDist(int haralickDist) {
this.haralickDist = haralickDist;
}
//</editor-fold>
}
//<editor-fold defaultstate="collapsed" desc="Coocurrence Matrix">
/**
* http://makseq.com/materials/lib/Articles-Books/Filters/Texture/Co-occurence/haralick73.pdf
*/
class Coocurrence {
/**
* The number of gray values for the textures
*/
private final int NUM_GRAY_VALUES;
/**
* The number of gray levels in an image
*/
private final int GRAY_RANGES = 256;
/**
* The scale for the gray values for conversion rgb to gray values.
*/
private final double GRAY_SCALE;
/**
* gray histogram of the image.
*/
private final double[] grayHistogram;
/**
* quantized gray values of each pixel of the image.
*/
private final byte[] grayValue;
/**
* mean gray value
*/
private double meanGrayValue = 0;
/**
* The cooccurrence matrix
*/
private final double[][] cooccurrenceMatrices;
/**
* The value for one increment in the gray/color histograms.
*/
private final int HARALICK_DIST;
private final ByteProcessor image;
public Coocurrence(ByteProcessor b, int numGrayValues, int haralickDist) {
this.NUM_GRAY_VALUES = numGrayValues;
this.image = b;
this.GRAY_SCALE = (double) GRAY_RANGES / (double) NUM_GRAY_VALUES;
this.cooccurrenceMatrices = new double[NUM_GRAY_VALUES][NUM_GRAY_VALUES];
this.grayValue = new byte[image.getPixelCount()];
this.grayHistogram = new double[GRAY_RANGES];
this.HARALICK_DIST = haralickDist;
calculate();
}
public double getMeanGrayValue() {
return this.meanGrayValue;
}
public double[][] getCooccurrenceMatrix() {
return this.cooccurrenceMatrices;
}
public double getCooccurenceSums() {
return image.getPixelCount() * 8;
}
private void calculate() {
calculateGreyValues();
final int imageWidth = image.getWidth();
final int imageHeight = image.getHeight();
final int d = HARALICK_DIST;
int i, j, pos;
// image is not empty per default
for (int y = 0; y < imageHeight; y++) {
for (int x = 0; x < imageWidth; x++) {
pos = imageWidth * y + x;
// horizontal neighbor: 0 degrees
i = x - d;
// j = y;
if (!(i < 0)) {
increment(grayValue[pos], grayValue[pos - d]);
}
// vertical neighbor: 90 degree
// i = x;
j = y - d;
if (!(j < 0)) {
increment(grayValue[pos], grayValue[pos - d * imageWidth]);
}
// 45 degree diagonal neigbor
i = x + d;
j = y - d;
if (i < imageWidth && !(j < 0)) {
increment(grayValue[pos], grayValue[pos + d - d * imageWidth]);
}
// 135 vertical neighbor
i = x - d;
j = y - d;
if (!(i < 0) && !(j < 0)) {
increment(grayValue[pos], grayValue[pos - d - d * imageWidth]);
}
}
}
meanGrayValue = Arrays2.sum(grayValue);
}
private void calculateGreyValues() {
int size = image.getPixelCount();
int gray;
for (int pos = 0; pos < size; pos++) {
gray = image.get(pos);
grayValue[pos] = (byte) (gray / GRAY_SCALE); // quantized for texture analysis
grayHistogram[gray]++;
}
Arrays2.div(grayHistogram, size);
}
/**
* Incremets the coocurrence matrix at the specified positions (g1,g2) and
* (g2,g1).
*
* #param g1 the gray value of the first pixel
* #param g2 the gray value of the second pixel
*/
private void increment(int g1, int g2) {
cooccurrenceMatrices[g1][g2]++;
cooccurrenceMatrices[g2][g1]++;
}
}
//</editor-fold>
Here you have the source.
Thanks in advance=)
I'm writing a ray tracer in java and I'm trying to implement refraction, but I'm getting confused by the information I'm finding on the subject. If I have a 3D vector for the incoming ray of light, the surface normal given as a 3D Vector and the refractive indexes of the two mediums what operations do I need to apply in order to get the vector of the transmitted ray?
Bram de Greve wrote a nice article about reflections and refractions in ray tracing. You can find it here.
His implementation (C++) looks like this:
Vector refract(const Vector& normal, const Vector& incident,
double n1, double n2)
{
const double n = n1 / n2;
const double cosI = -dot(normal, incident);
const double sinT2 = n * n * (1.0 - cosI * cosI);
if(sinT2 > 1.0) return Vector::invalid; // TIR
const double cosT = sqrt(1.0 - sinT2);
return n * incident + (n * cosI - cosT) * normal;
}
Here is the PBRTv3 implementation (under BSD-2-Clause license):
inline bool Refract(const Vector3f &wi, const Normal3f &n, Float eta,
Vector3f *wt) {
// Compute $\cos \theta_\roman{t}$ using Snell's law
Float cosThetaI = Dot(n, wi);
Float sin2ThetaI = std::max(Float(0), Float(1 - cosThetaI * cosThetaI));
Float sin2ThetaT = eta * eta * sin2ThetaI;
// Handle total internal reflection for transmission
if (sin2ThetaT >= 1) return false;
Float cosThetaT = std::sqrt(1 - sin2ThetaT);
*wt = eta * -wi + (eta * cosThetaI - cosThetaT) * Vector3f(n);
return true;
}
See my blog how to implement it test driven.
Let V_incedence be the normalized incoming vector. Let n1 and n2 be the refracting indices of the two surfaces. You want to calculate V_refraction. Let n be the normalized normal vector.
V_refraction = r*V_incedence + (rc - sqrt(1-Math.pow(r,2)(1-Math.pow(c,2))))n
where r = n1/n2 and c = -n dot V_incedence.
I implemented this in my ray java tracer take a look https://github.com/bradforj287/brads-java-raytracer
private static double clamp(final double val, final double min, final double max) {
return Math.max(min, Math.min(max, val));
}
private Vector3d getRefractionVector(final Vector3d I, final Vector3d N, final double ior) {
double cosi = clamp(-1, 1, I.dot(N));
double etai = 1, etat = ior;
Vector3d n = N;
if (cosi < 0) {
cosi = -cosi;
} else {
double temp = etai;
etai = etat;
etat = temp;
n = N.multiply(-1);
}
double eta = etai / etat;
double k = 1 - (eta * eta) * (1 - (cosi * cosi));
if (k <= 0) {
return Vector3d.ZERO;
} else {
return I.multiply(eta).add(n.multiply(((eta * cosi) - Math.sqrt(k))));
}
}
I'm trying to implement and train a five neuron neural network with back propagation for the XOR function in Java. My code (please excuse it's hideousness):
public class XORBackProp {
private static final int MAX_EPOCHS = 500;
//weights
private static double w13, w23, w14, w24, w35, w45;
private static double theta3, theta4, theta5;
//neuron outputs
private static double gamma3, gamma4, gamma5;
//neuron error gradients
private static double delta3, delta4, delta5;
//weight corrections
private static double dw13, dw14, dw23, dw24, dw35, dw45, dt3, dt4, dt5;
//learning rate
private static double alpha = 0.1;
private static double error;
private static double sumSqrError;
private static int epochs = 0;
private static boolean loop = true;
private static double sigmoid(double exponent)
{
return (1.0/(1 + Math.pow(Math.E, (-1) * exponent)));
}
private static void activateNeuron(int x1, int x2, int gd5)
{
gamma3 = sigmoid(x1*w13 + x2*w23 - theta3);
gamma4 = sigmoid(x1*w14 + x2*w24 - theta4);
gamma5 = sigmoid(gamma3*w35 + gamma4*w45 - theta5);
error = gd5 - gamma5;
weightTraining(x1, x2);
}
private static void weightTraining(int x1, int x2)
{
delta5 = gamma5 * (1 - gamma5) * error;
dw35 = alpha * gamma3 * delta5;
dw45 = alpha * gamma4 * delta5;
dt5 = alpha * (-1) * delta5;
delta3 = gamma3 * (1 - gamma3) * delta5 * w35;
delta4 = gamma4 * (1 - gamma4) * delta5 * w45;
dw13 = alpha * x1 * delta3;
dw23 = alpha * x2 * delta3;
dt3 = alpha * (-1) * delta3;
dw14 = alpha * x1 * delta4;
dw24 = alpha * x2 * delta4;
dt4 = alpha * (-1) * delta4;
w13 = w13 + dw13;
w14 = w14 + dw14;
w23 = w23 + dw23;
w24 = w24 + dw24;
w35 = w35 + dw35;
w45 = w45 + dw45;
theta3 = theta3 + dt3;
theta4 = theta4 + dt4;
theta5 = theta5 + dt5;
}
public static void main(String[] args)
{
w13 = 0.5;
w14 = 0.9;
w23 = 0.4;
w24 = 1.0;
w35 = -1.2;
w45 = 1.1;
theta3 = 0.8;
theta4 = -0.1;
theta5 = 0.3;
System.out.println("XOR Neural Network");
while(loop)
{
activateNeuron(1,1,0);
sumSqrError = error * error;
activateNeuron(0,1,1);
sumSqrError += error * error;
activateNeuron(1,0,1);
sumSqrError += error * error;
activateNeuron(0,0,0);
sumSqrError += error * error;
epochs++;
if(epochs >= MAX_EPOCHS)
{
System.out.println("Learning will take more than " + MAX_EPOCHS + " epochs, so program has terminated.");
System.exit(0);
}
System.out.println(epochs + " " + sumSqrError);
if (sumSqrError < 0.001)
{
loop = false;
}
}
}
}
If it helps any, here's a diagram of the network.
The initial values for all the weights and the learning rate are taken straight from an example in my textbook. The goal is to train the network until the sum of the squared errors is less than .001. The textbook also gives the values of all the weights after the first iteration (1,1,0) and I've tested my code and its results match the textbook's results perfectly. But according to the book, this should only take 224 epochs to converge. But when I run it, it always reaches MAX_EPOCHS unless it is set to several thousand. What am I doing wrong?
//Add this in the constants declaration section.
private static double alpha = 3.8, g34 = 0.13, g5 = 0.21;
// Add this in activate neuron
gamma3 = sigmoid(x1 * w13 + x2 * w23 - theta3);
gamma4 = sigmoid(x1 * w14 + x2 * w24 - theta4);
if (gamma3 > 1 - g34 ) {gamma3 = 1;}
if (gamma3 < g34) {gamma3 = 0;}
if (gamma4 > 1- g34) {gamma4 = 1;}
if (gamma4 < g34) {gamma4 = 0;}
gamma5 = sigmoid(gamma3 * w35 + gamma4 * w45 - theta5);
if (gamma5 > 1 - g5) {gamma5 = 1;}
if (gamma5 < g5) {gamma5 = 0;}
ANN should learn in 66 iterations, but is on the brink of divergence.
Try making rounding of gamma3, gamma4, gamma5 while in activation phase for instace:
if (gamma3 > 0.7) gamma3 = 1;
if (gamma3 < 0.3) gamma3 = 0;
and rise little bit learnig variable ( alpha )
alpha = 0.2;
learning ends in 466 epochs.
Of course if u make bigger rounding and higher alpha u set u can achieve even better result than 224.
Whole point of this network is to show how to deal with a situation when grouping isn't based on "top = yes, bottom = no", but rather there is a central line (going through points (0,1) and (1,0) in this case) and if value is close to the line, then answer is "yes", while if it is far, then answer is "no". You can't cluster such system with just one layer. However two layers is enough.
I want to compute the moment of inertia of a (2D) concave polygon. I found this on the internet. But I'm not very sure how to interpret the formula...
Formula http://img101.imageshack.us/img101/8141/92175941c14cadeeb956d8f.gif
1) Is this formula correct?
2) If so, is my convertion to C++ correct?
float sum (0);
for (int i = 0; i < N; i++) // N = number of vertices
{
int j = (i + 1) % N;
sum += (p[j].y - p[i].y) * (p[j].x + p[i].x) * (pow(p[j].x, 2) + pow(p[i].x, 2)) - (p[j].x - p[i].x) * (p[j].y + p[i].y) * (pow(p[j].y, 2) + pow(p[i].y, 2));
}
float inertia = (1.f / 12.f * sum) * density;
Martijn
#include <math.h> //for abs
float dot (vec a, vec b) {
return (a.x*b.x + a.y*b.y);
}
float lengthcross (vec a, vec b) {
return (abs(a.x*b.y - a.y*b.x));
}
...
do stuff
...
float sum1=0;
float sum2=0;
for (int n=0;n<N;++n) { //equivalent of the Σ
sum1 += lengthcross(P[n+1],P[n])*
(dot(P[n+1],P[n+1]) + dot(P[n+1],P[n]) + dot(P[n],P[n]));
sum2 += lengthcross(P[n+1],P[n]);
}
return (m/6*sum1/sum2);
Edit: Lots of small math changes
I think you have more work to do that merely translating formulas into code. You need to understand exactly what this formula means.
When you have a 2D polygon, you have three moments of inertia you can calculate relative to a given coordinate system: moment about x, moment about y, and polar moment of inertia. There's a parallel axis theorem that allows you to translate from one coordinate system to another.
Do you know precisely which moment and coordinate system this formula applies to?
Here's some code that might help you, along with a JUnit test to prove that it works:
import java.awt.geom.Point2D;
/**
* PolygonInertiaCalculator
* User: Michael
* Date: Jul 25, 2010
* Time: 9:51:47 AM
*/
public class PolygonInertiaCalculator
{
private static final int MIN_POINTS = 2;
public static double dot(Point2D u, Point2D v)
{
return u.getX()*v.getX() + u.getY()*v.getY();
}
public static double cross(Point2D u, Point2D v)
{
return u.getX()*v.getY() - u.getY()*v.getX();
}
/**
* Calculate moment of inertia about x-axis
* #param poly of 2D points defining a closed polygon
* #return moment of inertia about x-axis
*/
public static double ix(Point2D [] poly)
{
double ix = 0.0;
if ((poly != null) && (poly.length > MIN_POINTS))
{
double sum = 0.0;
for (int n = 0; n < (poly.length-1); ++n)
{
double twiceArea = poly[n].getX()*poly[n+1].getY() - poly[n+1].getX()*poly[n].getY();
sum += (poly[n].getY()*poly[n].getY() + poly[n].getY()*poly[n+1].getY() + poly[n+1].getY()*poly[n+1].getY())*twiceArea;
}
ix = sum/12.0;
}
return ix;
}
/**
* Calculate moment of inertia about y-axis
* #param poly of 2D points defining a closed polygon
* #return moment of inertia about y-axis
* #link http://en.wikipedia.org/wiki/Second_moment_of_area
*/
public static double iy(Point2D [] poly)
{
double iy = 0.0;
if ((poly != null) && (poly.length > MIN_POINTS))
{
double sum = 0.0;
for (int n = 0; n < (poly.length-1); ++n)
{
double twiceArea = poly[n].getX()*poly[n+1].getY() - poly[n+1].getX()*poly[n].getY();
sum += (poly[n].getX()*poly[n].getX() + poly[n].getX()*poly[n+1].getX() + poly[n+1].getX()*poly[n+1].getX())*twiceArea;
}
iy = sum/12.0;
}
return iy;
}
/**
* Calculate polar moment of inertia xy
* #param poly of 2D points defining a closed polygon
* #return polar moment of inertia xy
* #link http://en.wikipedia.org/wiki/Second_moment_of_area
*/
public static double ixy(Point2D [] poly)
{
double ixy = 0.0;
if ((poly != null) && (poly.length > MIN_POINTS))
{
double sum = 0.0;
for (int n = 0; n < (poly.length-1); ++n)
{
double twiceArea = poly[n].getX()*poly[n+1].getY() - poly[n+1].getX()*poly[n].getY();
sum += (poly[n].getX()*poly[n+1].getY() + 2.0*poly[n].getX()*poly[n].getY() + 2.0*poly[n+1].getX()*poly[n+1].getY() + poly[n+1].getX()*poly[n].getY())*twiceArea;
}
ixy = sum/24.0;
}
return ixy;
}
/**
* Calculate the moment of inertia of a 2D concave polygon
* #param poly array of 2D points defining the perimeter of the polygon
* #return moment of inertia
* #link http://www.physicsforums.com/showthread.php?t=43071
* #link http://www.physicsforums.com/showthread.php?t=25293
* #link http://stackoverflow.com/questions/3329383/help-me-with-converting-latex-formula-to-code
*/
public static double inertia(Point2D[] poly)
{
double inertia = 0.0;
if ((poly != null) && (poly.length > MIN_POINTS))
{
double numer = 0.0;
double denom = 0.0;
double scale;
double mag;
for (int n = 0; n < (poly.length-1); ++n)
{
scale = dot(poly[n + 1], poly[n + 1]) + dot(poly[n + 1], poly[n]) + dot(poly[n], poly[n]);
mag = Math.sqrt(cross(poly[n], poly[n+1]));
numer += mag * scale;
denom += mag;
}
inertia = numer / denom / 6.0;
}
return inertia;
}
}
Here's the JUnit test to accompany it:
import org.junit.Test;
import java.awt.geom.Point2D;
import static org.junit.Assert.assertEquals;
/**
* PolygonInertiaCalculatorTest
* User: Michael
* Date: Jul 25, 2010
* Time: 10:16:04 AM
*/
public class PolygonInertiaCalculatorTest
{
#Test
public void testTriangle()
{
Point2D[] poly =
{
new Point2D.Double(0.0, 0.0),
new Point2D.Double(1.0, 0.0),
new Point2D.Double(0.0, 1.0)
};
// Moment of inertia about the y1 axis
// http://www.efunda.com/math/areas/triangle.cfm
double expected = 1.0/3.0;
double actual = PolygonInertiaCalculator.inertia(poly);
assertEquals(expected, actual, 1.0e-6);
}
#Test
public void testSquare()
{
Point2D[] poly =
{
new Point2D.Double(0.0, 0.0),
new Point2D.Double(1.0, 0.0),
new Point2D.Double(1.0, 1.0),
new Point2D.Double(0.0, 1.0)
};
// Polar moment of inertia about z axis
// http://www.efunda.com/math/areas/Rectangle.cfm
double expected = 2.0/3.0;
double actual = PolygonInertiaCalculator.inertia(poly);
assertEquals(expected, actual, 1.0e-6);
}
#Test
public void testRectangle()
{
// This gives the moment of inertia about the y axis for a coordinate system
// through the centroid of the rectangle
Point2D[] poly =
{
new Point2D.Double(0.0, 0.0),
new Point2D.Double(4.0, 0.0),
new Point2D.Double(4.0, 1.0),
new Point2D.Double(0.0, 1.0)
};
double expected = 5.0 + 2.0/3.0;
double actual = PolygonInertiaCalculator.inertia(poly);
assertEquals(expected, actual, 1.0e-6);
double ix = PolygonInertiaCalculator.ix(poly);
double iy = PolygonInertiaCalculator.iy(poly);
double ixy = PolygonInertiaCalculator.ixy(poly);
assertEquals(ix, (1.0 + 1.0/3.0), 1.0e-6);
assertEquals(iy, (21.0 + 1.0/3.0), 1.0e-6);
assertEquals(ixy, 4.0, 1.0e-6);
}
}
For reference, here's a mutable 2D org.gcs.kinetic.Vector implementation and a more versatile, immutable org.jscience.mathematics.vector implementation. This article on Calculating a 2D Vector’s Cross Product is helpful, too.
I did it with Tesselation. And take the MOI's all together.