I am working on a graph implementation for a health app and the user can choose which fields to graph.
There are some combination of fields which never appear on the graph.
From the debugging I have done so far I can see that the values for all the fields are created correctly.
So ultimately my question is, why is there no line for "Weight Moving Average"
But really I would like to know how to debug this problem. What be the recommended next step for getting to the bottom of it?
Code:
if (isMovingAverage) {
dataset.mode = LineChartModeCubicBezier;
dataset.cubicIntensity = 0.1;
dataset.lineWidth = 2;
dataset.highlightEnabled = NO;
[dataset setColor: baseColor];
dataset.fillAlpha = 1.f;
dataset.drawCirclesEnabled = NO;
NSArray *gradientColors = #[
(id)[UIColor whiteColor].CGColor,
(id)baseColor.CGColor
];
CGGradientRef gradient = CGGradientCreateWithColors(nil, (CFArrayRef)gradientColors, nil);
dataset.fillAlpha = 1.f;
dataset.fill = [ChartFill fillWithLinearGradient:gradient angle:90.f];
dataset.drawFilledEnabled = YES;
dataset.drawHorizontalHighlightIndicatorEnabled = NO;
CGGradientRelease(gradient);
NSLog(#"Dataset: %#", dataset);
}
Debug output:
Formatting: Weight Moving Avg
2017-07-28 17:06:49.425518+0100 BodyTrackItLite[5239:1893083] Using color: UIExtendedSRGBColorSpace 0.07 0.62 0.64 1
2017-07-28 17:06:49.426723+0100 BodyTrackItLite[5239:1893083] Dataset: Charts.LineChartDataSet, label: Weight Moving Average, 140 entries
Metaphox was right in his comment, one dataset was blocking the others and so the solution was to remove the gradient fill.
I don't have a good answer as how best to approach debugging the charts component though.
Related
I am implementing this neural network for some classification problem. I initially tried back propagation but it takes longer to converge. So I though of using RPROP. In my test setup RPROP works fine for AND gate simulation but never converges for OR and XOR gate simulation.
How and when should I update bias for RPROP?
Here my weight update logic:
for(int l_index = 1; l_index < _total_layers; l_index++){
Layer* curr_layer = get_layer_at(l_index);
//iterate through each neuron
for (unsigned int n_index = 0; n_index < curr_layer->get_number_of_neurons(); n_index++) {
Neuron* jth_neuron = curr_layer->get_neuron_at(n_index);
double change = jth_neuron->get_change();
double curr_gradient = jth_neuron->get_gradient();
double last_gradient = jth_neuron->get_last_gradient();
int grad_sign = sign(curr_gradient * last_gradient);
//iterate through each weight of the neuron
for(int w_index = 0; w_index < jth_neuron->get_number_of_weights(); w_index++){
double current_weight = jth_neuron->give_weight_at(w_index);
double last_update_value = jth_neuron->give_update_value_at(w_index);
double new_update_value = last_update_value;
if(grad_sign > 0){
new_update_value = min(last_update_value*1.2, 50.0);
change = sign(curr_gradient) * new_update_value;
}else if(grad_sign < 0){
new_update_value = max(last_update_value*0.5, 1e-6);
change = -change;
curr_gradient = 0.0;
}else if(grad_sign == 0){
change = sign(curr_gradient) * new_update_value;
}
//Update neuron values
jth_neuron->set_change(change);
jth_neuron->update_weight_at((current_weight + change), w_index);
jth_neuron->set_last_gradient(curr_gradient);
jth_neuron->update_update_value_at(new_update_value, w_index);
double current_bias = jth_neuron->get_bias();
jth_neuron->set_bias(current_bias + _learning_rate * jth_neuron->get_delta());
}
}
}
In principal you don't treat the bias differently than before when you did backpropagation. It's learning_rate * delta which you seem to be doing.
One source of error may be that the sign of the weight change depends on how you calculate your error. There's different conventions and (t_i-y_i) instead of (y_i - t_i) should result in returning (new_update_value * sgn(grad)) instead of -(new_update_value * sign(grad)) so try switching the sign. I'm also unsure about how you specifically implemented everything since a lot is not shown here. But here's a snippet of mine in a Java implementation that might be of help:
// gradient didn't change sign:
if(weight.previousErrorGradient * errorGradient > 0)
weight.lastUpdateValue = Math.min(weight.lastUpdateValue * step_pos, update_max);
// changed sign:
else if(weight.previousErrorGradient * errorGradient < 0)
{
weight.lastUpdateValue = Math.max(weight.lastUpdateValue * step_neg, update_min);
}
else
weight.lastUpdateValue = weight.lastUpdateValue; // no change
// Depending on language, you should check for NaN here.
// multiply this with -1 depending on your error signal's sign:
return ( weight.lastUpdateValue * Math.signum(errorGradient) );
Also, keep in mind that 50.0, 1e-6 and especially 0.5, 1.2 are empirically gathered values so they might need to be adjusted. You should definitely print out the gradients and weight changes to see if there's something weird going on (e.g. exploding gradients->NaN although you're only testing AND/XOR). Your last_gradient value should also be initialized to 0 at the first timestep.
I worked a lot in it and can't find a solution. Even the title can't explain clearly.
I have three values weight, quantity and total
I had done the following
float wq = [[weightarray objectAtIndex:selectedint]floatValue];
float q = [quantity floatValue];
float total = wq * q;
for ex, if
[weightarray objectAtIndex:selectedint] = #"3.14";
quantity = 4;
then the result is
wq = 3.140000 q= 4.000000 total = 12.560000
but I need
wq = 3.14 total = 12.56
what to do?
I searched a lot, someone suggests to use NSDecimal,
NSDecimalNumberHandler *roundingBehavior = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundPlain scale:2 raiseOnExactness:FALSE raiseOnOverflow:TRUE raiseOnUnderflow:TRUE raiseOnDivideByZero:TRUE];
but the scale is not 2 here, wq value may have 3 or four numbers after point.
If the total = 2.30000100 means I need total = 2.300001
how to solve this?
I'm not entirely sure what it is your asking for, but it seems as if you want the values to only display a 2 d.p. In which case you could use a string format like so:
NSString *output = [NSString stringWithFormat:#"float = %.2f", 3.14];
The .2 specifies that the float should be justified to 2 d.p.
Hope this helps
There may be a more direct way to achieve it (which I don't know) but here's a suggestion...
Convert to string as you already do.
Use [myString hasSuffix:#"0"] to see if it ends in zero.
Use [myString substringToindex:[myString length]-1] to create a new string without the final zero.
Repeat.
I know it's not elegant, but unless someone has a better solution, this will at least do what you want.
UPDATE: scratch that - I just discovered [myString stringByTrimmingCharactersInSet:set]. Surely this must be what you need...?
Finally solution found, thanks to Martin
float total = 12.56000;
NSString *s = [NSString stringWithFormat:#"%f", total];
NSLog(#"%#",s);
BOOL success;
success =NO;
while(!success)
{
if ([s hasSuffix:#"0"])
{
s = [s substringWithRange:NSMakeRange(0,[s length]-1)];
}
else if ([s hasSuffix:#"."])
{
s = [s substringWithRange:NSMakeRange(0,[s length]-1)];
success = YES;
}
else
success = YES;
}
NSLog(#"%#",s);
if total = 12.560000 it returns total = 12.56
if total = 12.000000 it returns total = 12
if total = 10.000000 it returns total = 10
if total = 12.3000100 it returns total = 12.30001
Here's my code:
#define kDeselected .3
#define kSelected 1
- (void) selectButton:(UIImageView*)iconView{
[iconView setAlpha:kDeselected];
if(iconView.alpha == kDeselected){
[iconView setAlpha:kSelected];
}
else if(iconView.alpha == kSelected){
[iconView setAlpha:kDeselected];
}
}
I'm a pretty advanced programmer but it's beyond me as to why right before the if statement, when I manually went in and ensured that the if statement would result to true, it still doesn't hit it.
It should be noted that when kDeselected = .5, then it works perfectly. When it's .3 however...it doesn't like me.
Try casting your const to a float value as #define kDeselected 0.3f
It might be due to a compiler problem when casting your constant into a type
Try doing
CGFloat deselectedValue = kDeselected;
and see what it's value actually is, and try working with that:
- (void) selectButton:(UIImageView*)iconView{
CGFloat deselectedValue = kDeselected;
[iconView setAlpha:deselectedValue];
if(iconView.alpha == deselectedValue){
[iconView setAlpha:deselectedValue];
}
else if(iconView.alpha == kSelected){
[iconView setAlpha:kDeselected];
}
}
Your other option is to try and define your .3 as #define kDeselected 0.3f, however I doubt it'll make a difference if .5 works
I guess there is some limited precision in the storage of alpha in the iconView. It's probably returning 0.3334. Or thereabouts.
In image editing, it's rare to see an alpha value outside an 8-bit integer range. In fact, I don't think I've ever seen one.
I tried
for (int i = 0; i <100; i++) {
double myAlpha = 0.3 + i * 0.01;
self.view.alpha = myAlpha;
NSLog(#"myAlpha=%30.20f viewAlpha=%30.20f", myAlpha, self.view.alpha);
}
and saw
myAlpha= 0.29999999999999998890 viewAlpha= 0.30000001192092895508
myAlpha= 0.30999999999999999778 viewAlpha= 0.31000000238418579102
myAlpha= 0.32000000000000000666 viewAlpha= 0.31999999284744262695
myAlpha= 0.32999999999999996003 viewAlpha= 0.33000001311302185059
myAlpha= 0.33999999999999996891 viewAlpha= 0.34000000357627868652
so expecting the returned value of alpha to be anything other than an approximation looks like wishful thinking!
I am now using MIMChartLib to developer Iphone Chart,
But i am having trouble about the line chart,
for example
here is my CSV
Time;NAME;value001;value002;value003;value004;
01:00.0;ABCABC;1837;1837.2;1836.5;1831
02:00.0;ABCABC;1836.7;1837;1836.5;1836.7
03:00.0;ABCABC;1827;1827.2;1816.5;1826.9
04:00.0;ABCABC;1837;1837.2;1836.5;1836.9
05:00.0;ABCABC;1837;1837.2;1836.5;1836.9
How can i set the Y axis to be 18000, but not start from zero.
otherwise,the chart will show really really small.
here is preview:
here is my code
/*
Date;Time;Currency;Bid;Ask
14/9/2011;00:03.0;LLGUSD;1836.5;1837
*/
[MIMColor InitColors];
NSString *csvPath1 = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"myTableBar.csv"];
//LineGraph *lineGraph=[[LineGraph alloc]initWithFrame:CGRectMake(100, 20, 220, 380)];
LineGraph *lineGraph=[[LineGraph alloc]initWithFrame:Chartarea.frame];
lineGraph.needStyleSetter=YES;
lineGraph.xIsString=YES;
lineGraph.anchorType=CIRCLEBORDER; //OTHER anchorType
[lineGraph readFromCSV:csvPath1 titleAtColumn:1 valueInColumn:[NSArray arrayWithObjects:#"1",#"3", nil]];
[lineGraph displayYAxis];
[lineGraph displayXAxisWithStyle:5]; //OTHER styles FOR X-Axis Labels
[lineGraph drawWallGraph];
[self.view addSubview:lineGraph];
Thank you very much!!
go this link
https://github.com/ReetuRaj/MIMChart-Library
in YAxisBand.m file u have this method it work for me.....
-(void)setScaleForYTile:(float)value withNumOfLines:(int)numOfHorLines
{
pixelPerYTile=18000000.0;
//pixelPerYTile=value;
HorLines=numOfHorLines;
[self setNeedsDisplay];
}
go this link
https://github.com/ReetuRaj/MIMChart-Library
In MIMLineGraph.m
go to the function -(void)_findScaleForYTile
and REMOVE the following code
minOfY=[MIM_MathClass getMinFloatValue:[_yValElements objectAtIndex:0]];
for (int i=1; i<[_yValElements count]; i++)
{
float minOfY1=[MIM_MathClass getMinFloatValue:[_yValElements objectAtIndex:i]];
if(minOfY1<minOfY)
minOfY=minOfY1;
}
and set the value of minOfY directly as zero instead of doing the above calculation
minOfY = 18000000.0;
NOTE: in MIMChartLib minimum value plotted in yaxis will be the smallest value that you give in CSV file for plotting..so if u need to start yaxis from 18000000.0 then if the minimum value in your CSV file is the same then MIMCHART will automatically set the starting value of yaxis as 18000000.0
I'm making an UISlider and I don't find how to change the selectable values, I would like the only values possible be 10 by 10.
The slider begins at 82 and ends at 362. I want the possible value to be 82,92,102,.....
I've tried different things but I don't find
[sliderannonce setValue: [sliderannonce value]+10.0 animated:YES];
or
sliderannonce.value=10;
I've my action here:
- (IBAction)changeSliderAnnonce:(id)sender{
labelSliderAnnonce.text = [[NSString alloc] initWithFormat:#"annonce:%d",(int)sliderannonce.value];
}
If you did something like that or you know how to do please let me know.
Wouldn't it be simpler to just multiply the value by 10 in your code and add the starting value?
Example : start the slider at 0, end at 28 :
int position = 82 + ((int)sliderannonce.value) * 10;
Finally found a way to "cheat" with your idea thanks :D
I started to 8,2 and end to 36,2 and I multiply by 10
- (IBAction)changeSliderAnnonce:(id)sender{
int position= ((int)sliderannonce.value)*10+2;
labelSliderAnnonce.text = [[NSString alloc] initWithFormat:#"annonce: %d",((int)sliderannonce.value)*10+ 2];
NSLog(#"valeur de l'enchere: %d",position);
}