Asking review and help for implementing logistic regression model - java

I'm trying to implement a simple logistic regression model in Scala. That is there is only one independent variable to the dependent binary variable.
If we look as the example from Wikipedia: https://en.wikipedia.org/wiki/Logistic_regression (under section " Probability of passing an exam versus hours of study") and try to get the same coefficients for theta0 and theta1 with my current code we come close.
When the if-statement in the method gradientDescent is commented out theta0 = -4.360295851109452 and theta1 = 1.5166246438642796 with max iterations.
This is pretty close to the wikipedia example where theta0 = −4.0777 and theta1 = 1.5046.
If the if-statement is not commented out then theta0 = 0.0 and theta1 = 0.0 with only one itarations meaning that the return happens instantly.
I'm not sure why this is. Although I'm not even sure how far off am I from a working model.
In general I'm trying to implement what has been showed here: https://www.internalpointers.com/post/cost-function-logistic-regression
To my understanding: If we obtain the most optimas thetas with gradient descent then we can fit the S-curve to the original data points.
import scala.collection.mutable.Buffer
import scala.collection.mutable.ArrayBuffer
import scala.math.exp
import scala.math.abs
object Testing extends App {
val logistic = new LogisticRegressionCalculator
val yData = Array(0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1).map(z => z.toDouble)
val xData = Array.tabulate(20)({a => 0.5 + a * 0.25})
val thetas = logistic.deriveThetas(yData, xData)
println(thetas)
}
class LogisticRegressionCalculator {
//Learning rate
private var alpha = 0.01
//Tolerance
private var epsilon = 10E-10
//Number of iterations
private var maxIterations = 1000000
def changeAlpha(newAlpha: Double) = this.alpha = newAlpha
def changeEpsilon(newEpsilon: Double) = this.epsilon = newEpsilon
def changeMaxIterations(newMaxIter: Int) = this.maxIterations = newMaxIter
def giveAlpha: Double = this.alpha
def giveEpsilon: Double = this.epsilon
def giveMaxIterations: Int = this.maxIterations
/*
* This function is for the simple case where we have only one independent variable for the y values
* which are either zero or one.
* It is assumed that the left
*/
def deriveThetas(yData: Array[Double], xData: Array[Double]): Buffer[Double] = {
require(yData.size == xData.size)
//Traces below would be used for testing to see if the values obtained make sence
// val traceTheta0 = Array.ofDim[Double](this.maxIterations)
// val traceTheta1 = Array.ofDim[Double](this.maxIterations)
var theta0 = 0.0
var tempTheta0 = theta0
var theta1 = 0.0
var tempTheta1 = theta1
val dataSize = yData.size
var counter = 0
//Hypothesis function for logistic regression in the form of sigmoid function
def hypothesis(z: Double) = 1.0 / (1.0 + exp(-z))
def deriveTheta0: Double = {
var sum = 0.0
for (i <- 0 until dataSize) {
sum += (hypothesis(theta0 + theta1 * xData(i)) - yData(i)) //here should be * 1 as the coefficient of theta0 is 1.
}
return -(this.alpha / dataSize) * sum
}
def deriveTheta1: Double = {
var sum = 0.0
for (i <- 0 until dataSize) {
sum += (hypothesis(theta0 + theta1 * xData(i)) - yData(i)) * xData(i)
}
return -(this.alpha / dataSize) * sum
}
def gradientDescent: (Double, Double, Double) = {
for (i <- 0 until this.maxIterations) {
//println(s"Theta0: ${theta0}\tTheta1: ${theta1}")
counter += 1
tempTheta0 = theta0 + deriveTheta0
tempTheta1 = theta1 + deriveTheta1
//If the difference is so miniscule that further iterations are of no use.
// if (abs(tempTheta0 - theta0) >= epsilon || abs(tempTheta1 - theta1) >= epsilon) {
//
// return(theta0, theta1, counter)
//
// }
theta0 = tempTheta0
theta1 = tempTheta1
}
(theta0, theta1, counter)
}
val temp = gradientDescent
Buffer(temp._1, temp._2, counter)
}
}

Related

What does posenet return?

I'm working on a project which read an image as an input and show and output image. The output image contains some lines to indicate the human body skeleton. I'm using pose estimation model from tensorflow-lite:
https://www.tensorflow.org/lite/models/pose_estimation/overview
I have read the docs, and it shows that the output contains a 4-dimensions array. I have tried to use netron to visualize my model file and it looks like this:
I succeeded to get the result heatmap from the input but I got a problem that all the float are negative. It makes me confused and I'm not sure if I did anything wrong or how to understand these outputs.
Here's the code for the output
tfLite = new Interpreter(loadModelFile());
Bitmap inputPhoto = BitmapFactory.decodeResource(getResources(), R.drawable.human2);
inputPhoto = Bitmap.createScaledBitmap(inputPhoto, INPUT_SIZE_X, INPUT_SIZE_Y, false);
inputPhoto = inputPhoto.copy(Bitmap.Config.ARGB_8888, true);
int pixels[] = new int[INPUT_SIZE_X * INPUT_SIZE_Y];
inputPhoto.getPixels(pixels, 0, INPUT_SIZE_X, 0, 0, INPUT_SIZE_X, INPUT_SIZE_Y);
int pixelsIndex = 0;
for (int i = 0; i < INPUT_SIZE_X; i ++) {
for (int j = 0; j < INPUT_SIZE_Y; j++) {
int p = pixels[pixelsIndex];
inputData[0][i][j][0] = (p >> 16) & 0xff;
inputData[0][i][j][1] = (p >> 8) & 0xff;
inputData[0][i][j][2] = (p) & 0xff;
pixelsIndex ++;
}
}
float outputData[][][][] = new float[1][23][17][17];
tfLite.run(inputData, outputData);
The output is an array [1][23][17][17] which is all negative. So is there anyone who known about this can help me :(
Thanks a lot !
This post came Active today so I post a late answer, sorry about that.
You should check the Posenet.kt file. There you can see a very detailed documented code. You can see how this:
Initializes an outputMap of 1 * x * y * z FloatArrays for the model processing to populate.
*/
private fun initOutputMap(interpreter: Interpreter): HashMap<Int, Any> {
val outputMap = HashMap<Int, Any>()
// 1 * 9 * 9 * 17 contains heatmaps
val heatmapsShape = interpreter.getOutputTensor(0).shape()
outputMap[0] = Array(heatmapsShape[0]) {
Array(heatmapsShape[1]) {
Array(heatmapsShape[2]) { FloatArray(heatmapsShape[3]) }
}
}
// 1 * 9 * 9 * 34 contains offsets
val offsetsShape = interpreter.getOutputTensor(1).shape()
outputMap[1] = Array(offsetsShape[0]) {
Array(offsetsShape[1]) { Array(offsetsShape[2]) { FloatArray(offsetsShape[3]) } }
}
// 1 * 9 * 9 * 32 contains forward displacements
val displacementsFwdShape = interpreter.getOutputTensor(2).shape()
outputMap[2] = Array(offsetsShape[0]) {
Array(displacementsFwdShape[1]) {
Array(displacementsFwdShape[2]) { FloatArray(displacementsFwdShape[3]) }
}
}
// 1 * 9 * 9 * 32 contains backward displacements
val displacementsBwdShape = interpreter.getOutputTensor(3).shape()
outputMap[3] = Array(displacementsBwdShape[0]) {
Array(displacementsBwdShape[1]) {
Array(displacementsBwdShape[2]) { FloatArray(displacementsBwdShape[3]) }
}
}
return outputMap
}
and of course how the output is transformed to points on screen:
/**
* Estimates the pose for a single person.
* args:
* bitmap: image bitmap of frame that should be processed
* returns:
* person: a Person object containing data about keypoint locations and confidence scores
*/
fun estimateSinglePose(bitmap: Bitmap): Person {
val estimationStartTimeNanos = SystemClock.elapsedRealtimeNanos()
val inputArray = arrayOf(initInputArray(bitmap))
Log.i(
"posenet",
String.format(
"Scaling to [-1,1] took %.2f ms",
1.0f * (SystemClock.elapsedRealtimeNanos() - estimationStartTimeNanos) / 1_000_000
)
)
val outputMap = initOutputMap(getInterpreter())
val inferenceStartTimeNanos = SystemClock.elapsedRealtimeNanos()
getInterpreter().runForMultipleInputsOutputs(inputArray, outputMap)
lastInferenceTimeNanos = SystemClock.elapsedRealtimeNanos() - inferenceStartTimeNanos
Log.i(
"posenet",
String.format("Interpreter took %.2f ms", 1.0f * lastInferenceTimeNanos / 1_000_000)
)
val heatmaps = outputMap[0] as Array<Array<Array<FloatArray>>>
val offsets = outputMap[1] as Array<Array<Array<FloatArray>>>
val height = heatmaps[0].size
val width = heatmaps[0][0].size
val numKeypoints = heatmaps[0][0][0].size
// Finds the (row, col) locations of where the keypoints are most likely to be.
val keypointPositions = Array(numKeypoints) { Pair(0, 0) }
for (keypoint in 0 until numKeypoints) {
var maxVal = heatmaps[0][0][0][keypoint]
var maxRow = 0
var maxCol = 0
for (row in 0 until height) {
for (col in 0 until width) {
if (heatmaps[0][row][col][keypoint] > maxVal) {
maxVal = heatmaps[0][row][col][keypoint]
maxRow = row
maxCol = col
}
}
}
keypointPositions[keypoint] = Pair(maxRow, maxCol)
}
// Calculating the x and y coordinates of the keypoints with offset adjustment.
val xCoords = IntArray(numKeypoints)
val yCoords = IntArray(numKeypoints)
val confidenceScores = FloatArray(numKeypoints)
keypointPositions.forEachIndexed { idx, position ->
val positionY = keypointPositions[idx].first
val positionX = keypointPositions[idx].second
yCoords[idx] = (
position.first / (height - 1).toFloat() * bitmap.height +
offsets[0][positionY][positionX][idx]
).toInt()
xCoords[idx] = (
position.second / (width - 1).toFloat() * bitmap.width +
offsets[0][positionY]
[positionX][idx + numKeypoints]
).toInt()
confidenceScores[idx] = sigmoid(heatmaps[0][positionY][positionX][idx])
}
val person = Person()
val keypointList = Array(numKeypoints) { KeyPoint() }
var totalScore = 0.0f
enumValues<BodyPart>().forEachIndexed { idx, it ->
keypointList[idx].bodyPart = it
keypointList[idx].position.x = xCoords[idx]
keypointList[idx].position.y = yCoords[idx]
keypointList[idx].score = confidenceScores[idx]
totalScore += confidenceScores[idx]
}
person.keyPoints = keypointList.toList()
person.score = totalScore / numKeypoints
return person
}
The whole .kt file is the heart of bitmap to points on screen!
If you need anything else tag me.
Happy coding

I am trying to calculate sine of an angle without using the Math.sin() in java

I am trying to calculate sine of an angle without using the Math.sin(). I got stuck in it's equation as I keep getting the wrong results
note I have a method that changes the angle from degrees to radians
public static double sin(double x, int precision) {
//this method is simply the sine function
double answer = 1, power = 1;
int n = 2,factorial = 1;
while (n<=precision) {
power = (power * x * x *-1) +1 ;
factorial = (factorial * (n +1))* (n-1);
answer = answer + ((power/factorial ));
n = n + 2;
}
return answer;
}
It looks like you're attempting to calculate the sine of angle given in radians using the Maclaurin series, a special case of Taylor series.
sin(x) = x - x^3/3! + x^5/5! - x^7/7! + ...
Your initial answer is 1 when it should be x. Your initial power is 1 when it should be x also.
double answer = x, power = x;
For some reason you're adding one to the power part of the result when you shouldn't be.
power = (power * x * x * -1);
You'll also need to fix your factorial calculation. Multiply by n + 1 and n, not n + 1 and n - 1.
factorial = (factorial * (n + 1)) * (n);
With these fixes, testing:
for (double angle = 0; angle <= Math.PI; angle += Math.PI / 4)
{
System.out.println("sin(" + angle + ") = " + sin(angle, 10));
}
The results are pretty good considering the limitations of precision for floating point arithmetic.
sin(0.0) = 0.0
sin(0.7853981633974483) = 0.7071067811796194
sin(1.5707963267948966) = 0.999999943741051
sin(2.356194490192345) = 0.7070959900908971
sin(3.141592653589793) = -4.4516023820965686E-4
Note that this will get more inaccurate as the values of x get larger, not just because of the inaccuracy to represent pi, but also because of the floating point calculations for adding and subtracting large values.

How do I fix this heart?

Seeing as Valentine's Day is fast approaching, I decided to create a heart. So I found this heart from mathematica.se:
I played around in Mathematica (solved for z, switching some variables around) to get this equation for the z-value of the heart, given the x and y values (click for full-size):
I faithfully ported this equation to Java, dealing with a couple out-of-bounds cases:
import static java.lang.Math.cbrt;
import static java.lang.Math.pow;
import static java.lang.Math.sqrt;
...
public static double heart(double xi, double yi) {
double x = xi;
double y = -yi;
double temp = 5739562800L * pow(y, 3) + 109051693200L * pow(x, 2) * pow(y, 3)
- 5739562800L * pow(y, 5);
double temp1 = -244019119519584000L * pow(y, 9) + pow(temp, 2);
//
if (temp1 < 0) {
return -1; // this is one possible out of bounds location
// this spot is the location of the problem
}
//
double temp2 = sqrt(temp1);
double temp3 = cbrt(temp + temp2);
if (temp3 != 0) {
double part1 = (36 * cbrt(2) * pow(y, 3)) / temp3;
double part2 = 1 / (10935 * cbrt(2)) * temp3;
double looseparts = 4.0 / 9 - 4.0 / 9 * pow(x, 2) - 4.0 / 9 * pow(y, 2);
double sqrt_body = looseparts + part1 + part2;
if (sqrt_body >= 0) {
return sqrt(sqrt_body);
} else {
return -1; // this works; returns -1 if we are outside the heart
}
} else {
// through trial and error, I discovered that this should
// be an ellipse (or that it is close enough)
return Math.sqrt(Math.pow(2.0 / 3, 2) * (1 - Math.pow(x, 2)));
}
}
The only problem is that when temp1 < 0, I cannot simply return -1, like I do:
if (temp1 < 0) {
return -1; // this is one possible out of bounds location
// this spot is the location of the problem
}
That's not the behavior of the heart at that point. As it is, when I try to make my image:
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import static java.lang.Math.cbrt;
import static java.lang.Math.pow;
import static java.lang.Math.sqrt;
public class Heart {
public static double scale(int x, int range, double l, double r) {
double width = r - l;
return (double) x / (range - 1) * width + l;
}
public static void main(String[] args) throws IOException {
BufferedImage img = new BufferedImage(1000, 1000, BufferedImage.TYPE_INT_RGB);
// this is actually larger than the max heart value
final double max_heart = 0.679;
double max = 0.0;
for (int x = 0; x < img.getWidth(); x++) {
for (int y = 0; y < img.getHeight(); y++) {
double xv = scale(x, img.getWidth(), -1.2, 1.2);
double yv = scale(y, img.getHeight(), -1.3, 1);
double heart = heart(xv, yv); //this isn't an accident
// yes I don't check for the return of -1, but still
// the -1 values return a nice shade of pink: 0xFFADAD
// None of the other values should be negative, as I did
// step through from -1000 to 1000 in python, and there
// were no negatives that were not -1
int r = 0xFF;
int gb = (int) (0xFF * (max_heart - heart));
int rgb = (r << 16) | (gb << 8) | gb;
img.setRGB(x, y, rgb);
}
}
ImageIO.write(img, "png", new File("location"));
}
// heart function clipped; it belongs here
}
I get this:
Look at that dip at the top! I tried changing that problematic -1 to a .5, resulting in this:
Now the heart has horns. But it becomes clear where that problematic if's condition is met.
How can I fix this problem? I don't want a hole in my heart at the top, and I don't want a horned heart. If I could clip the horns to the shape of a heart, and color the rest appropriately, that would be perfectly fine. Ideally, the two sides of the heart would come together as a point (hearts have a little point at the join), but if they curve together like shown in the horns, that would be fine too. How can I achieve this?
The problem is simple. If we look at that horseshoe region, we get imaginary numbers. For part of it, it should belong to our heart. In that region, if we were to evaluate our function (by math, not by programming), the imaginary parts of the function cancel. So it should look like this (generated in Mathematica):
Basically, the function for that part is almost identical; we just have to do arithmetic with complex numbers instead of real numbers. Here's a function that does exactly that:
private static double topOfHeart(double x, double y, double temp, double temp1) {
//complex arithmetic; each double[] is a single number
double[] temp3 = cbrt_complex(temp, sqrt(-temp1));
double[] part1 = polar_reciprocal(temp3);
part1[0] *= 36 * cbrt(2) * pow(y, 3);
double[] part2 = temp3;
part2[0] /= (10935 * cbrt(2));
toRect(part1, part2);
double looseparts = 4.0 / 9 - 4.0 / 9 * pow(x, 2) - 4.0 / 9 * pow(y, 2);
double real_part = looseparts + part1[0] + part2[0];
double imag_part = part1[1] + part2[1];
double[] result = sqrt_complex(real_part, imag_part);
toRect(result);
// theoretically, result[1] == 0 should work, but floating point says otherwise
if (Math.abs(result[1]) < 1e-5) {
return result[0];
}
return -1;
}
/**
* returns a specific cuberoot of this complex number, in polar form
*/
public static double[] cbrt_complex(double a, double b) {
double r = Math.hypot(a, b);
double theta = Math.atan2(b, a);
double cbrt_r = cbrt(r);
double cbrt_theta = 1.0 / 3 * (2 * PI * Math.floor((PI - theta) / (2 * PI)) + theta);
return new double[]{cbrt_r, cbrt_theta};
}
/**
* returns a specific squareroot of this complex number, in polar form
*/
public static double[] sqrt_complex(double a, double b) {
double r = Math.hypot(a, b);
double theta = Math.atan2(b, a);
double sqrt_r = Math.sqrt(r);
double sqrt_theta = 1.0 / 2 * (2 * PI * Math.floor((PI - theta) / (2 * PI)) + theta);
return new double[]{sqrt_r, sqrt_theta};
}
public static double[] polar_reciprocal(double[] polar) {
return new double[]{1 / polar[0], -polar[1]};
}
public static void toRect(double[]... polars) {
for (double[] polar: polars) {
double a = Math.cos(polar[1]) * polar[0];
double b = Math.sin(polar[1]) * polar[0];
polar[0] = a;
polar[1] = b;
}
}
To join this with your program, simply change your function to reflect this:
if (temp1 < 0) {
return topOfHeart(x, y, temp, temp1);
}
And running it, we get the desired result:
It should be pretty clear that this new function implements exactly the same formula. But how does each part work?
double[] temp3 = cbrt_complex(temp, sqrt(-temp1));
cbrt_complex takes a complex number in the form of a + b i. That's why the second argument is simply sqrt(-temp1) (notice that temp1 < 0, so I use - instead of Math.abs; Math.abs is probably a better idea). cbrt_complex returns the cube root of the complex number, in polar form: r eiθ. We can see from wolframalpha that with positive r and θ, we can write an n-th root of a complex numbers as follows:
And that's exactly how the code for the cbrt_complex and sqrt_complex work. Note that both take a complex number in rectangular coordinates (a + b i) and return a complex number in polar coordinates (r eiθ)
double[] part1 = polar_reciprocal(temp3);
It is easier to take the reciprocal of a polar complex number than a rectangular complex number. If we have r eiθ, its reciprocal (this follows standard power rules, luckily) is simply 1/r e-iθ. This is actually why we are staying in polar form; polar form makes multiplication-type operations easier, and addition type operations harder, while rectangular form does the opposite.
Notice that if we have a polar complex number r eiθ and we want to multiply by a real number d, the answer is as simple as d r eiθ.
The toRect function does exactly what it seems like it does: it converts polar coordinate complex numbers to rectangular coordinate complex numbers.
You may have noticed that the if statement doesn't check that there is no imaginary part, but only if the imaginary part is really small. This is because we are using floating point numbers, so checking result[1] == 0 will likely fail.
And there you are! Notice that we could actually implement the entire heart function with this complex number arithmetic, but it's probably faster to avoid this.

How can you find the point on an ellipse that sweeps a given area?

I am working on the problem of dividing an ellipse into equal sized segments. This question has been asked but the answers suggested numerical integration so that I what I'm attempting. This code short-circuits the sectors so the integration itself should never cover more than 90 degrees. The integration itself is being done by totaling the area of intermediate triangles. Below is the code I have tried, but it is sweeping more than 90 degrees in some cases.
public class EllipseModel {
protected double r_x;
protected double r_y;
private double a,a2;
private double b,b2;
boolean flip;
double area;
double sector_area;
double radstep;
double rot;
int xp,yp;
double deviation;
public EllipseModel(double r_x, double r_y, double deviation)
{
this.r_x = r_x;
this.r_y = r_y;
this.deviation = deviation;
if (r_x < r_y) {
flip = true;
a = r_y;
b = r_x;
xp = 1;
yp = 0;
rot = Math.PI/2d;
} else {
flip = false;
xp = 0;
yp = 1;
a = r_x;
b = r_y;
rot = 0d;
}
a2 = a * a;
b2 = b * b;
area = Math.PI * r_x * r_y;
sector_area = area / 4d;
radstep = (2d * deviation) / a;
}
public double getArea() {
return area;
}
public double[] getSweep(double sweep_area)
{
System.out.println(String.format("getSweep(%f) a = %f b = %f deviation = %f",sweep_area,a,b,deviation));
double[] ret = new double[2];
double[] next = new double[2];
double t_base, t_height, swept,x_mid,y_mid;
double t_area;
sweep_area = sweep_area % area;
if (sweep_area < 0d) {
sweep_area = area + sweep_area;
}
if (sweep_area == 0d) {
ret[0] = r_x;
ret[1] = 0d;
return ret;
}
double sector = Math.floor(sweep_area/sector_area);
double theta = Math.PI * sector/2d;
double theta_last = theta;
System.out.println(String.format("- Theta start = %f",Math.toDegrees(theta)));
ret[xp] = a * Math.cos(theta + rot);
ret[yp] = (1 + (((theta / Math.PI) % 2d) * -2d)) * Math.sqrt((1 - ( (ret[xp] * ret[xp])/a2)) * b2);
next[0] = ret[0];
next[1] = ret[1];
swept = sector * sector_area;
System.out.println(String.format("- Sweeping for %f sector_area=%f",sweep_area-swept,sector_area));
int c = 0;
while(swept < sweep_area) {
c++;
ret[0] = next[0];
ret[1] = next[1];
theta_last = theta;
theta += radstep;
// calculate next point
next[xp] = a * Math.cos(theta + rot);
next[yp] = (1 + (((theta / Math.PI) % 2d) * -2d)) * // selects +/- sqrt
Math.sqrt((1 - ( (ret[xp] * ret[xp])/a2)) * b2);
// calculate midpoint
x_mid = (ret[xp] + next[xp]) / 2d;
y_mid = (ret[yp] + next[yp]) / 2d;
// calculate triangle metrics
t_base = Math.sqrt( ( (ret[0] - next[0]) * (ret[0] - next[0]) ) + ( (ret[1] - next[1]) * (ret[1] - next[1])));
t_height = Math.sqrt((x_mid * x_mid) + (y_mid * y_mid));
// add triangle area to swept
t_area = 0.5d * t_base * t_height;
swept += t_area;
}
System.out.println(String.format("- Theta end = %f (%d)",Math.toDegrees(theta_last),c));
return ret;
}
}
In the output I see the following case where it sweeps over 116 degrees.
getSweep(40840.704497) a = 325.000000 b = 200.000000 deviation = 0.166667
- Theta start = 0.000000
- Sweeping for 40840.704497 sector_area=51050.880621
- Theta end = 116.354506 (1981)
Is there any way to fix the integration formula to create a function that returns the point on an ellipse that has swept a given area? The application that is using this code divides the total area by the number of segments needed, and then uses this code to determine the angle where each segment starts and ends. Unfortunately it doesn't work as intended.
* edit *
I believe the above integration failed because the base and height formula's aren't correct.
No transformation needed use parametric equations for ellipse ...
x=x0+rx*cos(a)
y=y0+ry*sin(a)
where a = < 0 , 2.0*M_PI >
if you divide ellipse by lines from center to x,y from above equation
and angle a is evenly encreased
then the segments will have the same size
btw. if you apply affine transform you will get the same result (even the same equation)
This code will divide ellipse to evenly sized chunks:
double a,da,x,y,x0=0,y0=0,rx=50,ry=20; // ellipse x0,y0,rx,ry
int i,N=32; // divided to N = segments
da=2.0*M_PI/double(N);
for (a=0.0,i=0;i<N;i++,a+=da)
{
x=x0+(rx*cos(a));
y=y0+(ry*sin(a));
// draw_line(x0,y0,x,y);
}
This is what it looks like for N=5
[edit1]
I do not understood from your comment what exactly you want to achieve now
sorry but my English skills are horrible
ok I assume these two possibilities (if you need something different please specify closer)
0.but first some global or member stuff needed
double x0,y0,rx,ry; // ellipse parameters
// [Edit2] sorry forgot to add these constants but they are I thin straight forward
const double pi=M_PI;
const double pi2=2.0*M_PI;
// [/Edit2]
double atanxy(double x,double y) // atan2 return < 0 , 2.0*M_PI >
{
int sx,sy;
double a;
const double _zero=1.0e-30;
sx=0; if (x<-_zero) sx=-1; if (x>+_zero) sx=+1;
sy=0; if (y<-_zero) sy=-1; if (y>+_zero) sy=+1;
if ((sy==0)&&(sx==0)) return 0;
if ((sx==0)&&(sy> 0)) return 0.5*pi;
if ((sx==0)&&(sy< 0)) return 1.5*pi;
if ((sy==0)&&(sx> 0)) return 0;
if ((sy==0)&&(sx< 0)) return pi;
a=y/x; if (a<0) a=-a;
a=atan(a);
if ((x>0)&&(y>0)) a=a;
if ((x<0)&&(y>0)) a=pi-a;
if ((x<0)&&(y<0)) a=pi+a;
if ((x>0)&&(y<0)) a=pi2-a;
return a;
}
1.is point inside segment ?
bool is_pnt_in_segment(double x,double y,int segment,int segments)
{
double a;
a=atanxy(x-x0,y-y0); // get sweep angle
a/=2.0*M_PI; // convert angle to a = <0,1>
if (a>=1.0) a=0.0; // handle extreme case where a was = 2 Pi
a*=segments; // convert to segment index a = <0,segments)
a-=double(segment );
// return floor(a); // this is how to change this function to return points segment id
// of course header should be slightly different: int get_pnt_segment_id(double x,double y,int segments)
if (a< 0.0) return false; // is lower then segment
if (a>=1.0) return false; // is higher then segment
return true;
}
2.get edge point of segment area
void get_edge_pnt(double &x,double &y,int segment,int segments)
{
double a;
a=2.0*M_PI/double(segments);
a*=double(segment); // this is segments start edge point
//a*=double(segment+1); // this is segments end edge point
x=x0+(rx*cos(a));
y=y0+(ry*sin(a));
}
for booth:
x,y is point
segments number of division segments.
segment is sweep-ed area < 0,segments )
Apply an affine transformation to turn your ellipse into a circle, preferrably the unit circle. Then split that into equal sized segments, before you apply the inverse transform. The transformation will scale all areas (as opposed to lengths) by the same factor, so equal area translates to equal area.

Testing Logistic Regression. Doesn't converge using 1 or 0, but does using logit

I have created a simple Logistic Regression using gradient descent using my linear regression code from here:
Gradient Descent Linear Regression in Java
Now I'm simply adapting it for Logistic Regression by changing the hypothesis by adding the logit transform: 1/(1+e^(-z)), where z is the original Theta^T * X. And not scaling by the population size.
When trying to test my results I get a confusing behavior: I set the independent variables(X) to a random number * an expected weight and the dependent(Y) to the logit of their sum, So y= logit(w0*1 + w1*x1 + w2*x2).
Now in this case it converges to the correct answer, and I can recover the expected weights. But obviously I should have Y as 0 or 1. But when I round up or down, I no longer converge.
Here I am generating training data:
#Test
public void testLogisticDescentMultiple() {
//...
//initialize Independent Xi
//Going to create test data y= 10 + .5(x1) + .33(x2)
for( int x=0;x<NUM_EXAMPLES;x++) {
independent.set(x, 0, 1); //x0 We always set this to 1 for the intercept
independent.set(x, 1, random.nextGaussian()); //x1
independent.set(x, 2, random.nextGaussian() ); //x2
}
//initialize dependent Yi
for( int x=0;x<NUM_EXAMPLES;x++) {
double val = w0 + (w1*independent.get(x,1)) + (w2*independent.get(x,2));
double logitVal = logit( val );
//Converges without this code block
if( logitVal < 0.5 ) {
logitVal = 0;
}else {
logitVal = 1;
}
//
dependent.set(x, logitVal );
}
//...
}
public static double logit( double val ) {
return( 1.0 / (1.0 + Math.exp(-val)));
}
//updated Logistic Regression
public DoubleMatrix1D logisticDescent(double alpha,
DoubleMatrix1D thetas,
DoubleMatrix2D independent,
DoubleMatrix1D dependent ) {
Algebra algebra = new Algebra();
//hypothesis is 1/( 1+ e ^ -(theta(Transposed) * X))
//start with theata(Transposed)*X
DoubleMatrix1D hypothesies = algebra.mult( independent, thetas );
//h = 1/(1+ e^-h)
hypothesies.assign(new DoubleFunction() {
#Override
public double apply (double val) {
return( logit( val ) );
}
});
//hypothesis - Y
//Now we have for each Xi, the difference between predicted by the hypothesis and the actual Yi
hypothesies.assign(dependent, Functions.minus);
//Transpose Examples(MxN) to NxM so we can matrix multiply by hypothesis Nx1
DoubleMatrix2D transposed = algebra.transpose(independent);
DoubleMatrix1D deltas = algebra.mult(transposed, hypothesies );
// thetas = thetas - (deltas*alpha) in one step
thetas.assign(deltas, Functions.minusMult(alpha));
return( thetas );
}

Categories