How can I check if a float variable is NaN or inf. Searching the standard library for isNaN or isInf does not reveal anything. There is a blog post suggesting to use
proc cIsNaN(x: float): int {.importc: "isnan", header: "<math.h>".}
but is there really nothing in the standard library?
The standard library does provide checking for NaN/inf, but under the generalized concept of classify, which is why it is easy to miss. To illustrate:
import math
# Inf and NaN literals are defined in system.nim as
# Inf* {.magic: "Inf".} = 1.0 / 0.0
# NaN* {.magic: "NaN".} = 0.0 / 0.0
let floatsToTest = [0.0, Inf, NaN]
for x in floatsToTest:
echo x, " is NaN ", x.classify == fcNaN
echo x, " is inf ", x.classify == fcInf
Output:
0.0 is NaN false
0.0 is inf false
inf is NaN false
inf is inf true
nan is NaN true
nan is inf false
classify can also test for other properties like fcSubnormal, fcNegZero, or fcNegInf (see FloatClass).
You can add your own function
import std/math
func is_number*(n: float): bool =
let ntype = n.classify
ntype == fc_normal or ntype == fc_zero or ntype == fc_neg_zero
Related
df=pd.DataFrame({"x":[1,2,3,0],"y":[1,1,1,1]})
df.groupby("y").agg(x_sum=("x",np.mean))
This code gives average of x, the output is 1.5 ((1+2+3+0)/4=1.5)
but I want average of x where the number of larger than 0, so the output should be (1+2+3)/3=2.
How should I address it?
Replace not greater like 0 in x column to NaN:
df.x = df.x.where(df.x.gt(0))
#alternative
#df.x = df.x.mask(df.x.le(0))
print (df)
x y
0 1.0 1
1 2.0 1
2 3.0 1
3 NaN 1
df1 = df.groupby("y").agg(x_sum=("x",np.mean))
print (df1)
x_sum
y
1 2.0
You can write and use your custom function. Example:
import pandas as pd
import numpy as np
def mean_without_zero_values(values):
vals = [v for v in values if v > 0]
return np.mean(vals)
df=pd.DataFrame({"x":[1,2,3,0],"y":[1,1,1,1]})
result = df.groupby("y").agg(x_sum=("x",mean_without_zero_values))
print(result)
# output
# x_sum
# y
# 1 2
import numpy as np
n = 10
xmin = 0
xmax = 1
dx = 1/n
x = np.arange(xmin-dx, xmax + 2*dx, dx)
print(x)
print(x <= 0.3)
The output of this code is following :
[-0.1 0. 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1. 1.1]
[ True True True True False False False False False False False False
False]
Why the element in array with value 0.3 is not smaller or equal than 0.3?
I tried the same with other comparasions and i saw that -0.1 <= -0.1 and 0.1 <= 0.1 while 0.2 is not less or equal 0.2.
Really do not understand what is happening here.
I got it. Never compare float numbers, because of round-off error.
This will work:
print(x <= 0.3 + np.finfo(np.float64).eps)
import pandas as pd
import matplotlib.pyplot as plt
# I'm trying to code the utter basic func of LinearRegression
# from sklearn.linear_model import LinearRegression
dataframe = pd.read_fwf('brain_body.txt') # link given below
x_values = dataframe[['Brain']]
y_values = dataframe[['Body']]
lr = LinearRegression(0.0001, 10) # sending learning_rate and iterations
lr.fit(x_values, y_values)
# commenting out because the values are insane
# plt.scatter(x_values, y_values)
# plt.plot(x_values, clf.predict(x_values))
# plt.show()
Link to brain_body.txt
Here's the class I've written
class LinearRegression:
def __init__(self, learning_rate, iterations):
self.b = 0 # b as in y=mx+b
self.m = 0 # m as in y=mx+b
self.learning_rate = learning_rate
self.iterations = iterations
def get_y(self, x):
return self.m * float(x) + self.b
def step_gradient(self, x_values, y_values):
print()
print("Values before: m =", self.m, " b =", self.b)
m_gradient = 0
b_gradient = 0
N = float(len(x_values.ix[:, 0]))
print('%11s' % "d(m)", '%11s' % "m_gradient", '%11s' % "d(b)", '%11s' % "b_gradient")
for i in range(int(N)):
x = x_values.iloc[i][0]
y = y_values.iloc[i][0]
# EDIT: I missed a * -1 here
# But that wouldn't just fix everything, adjusting learning rate does
pm = (y - self.get_y(x)) * x # partial derivative of m
pb = (y - self.get_y(x)) * -1 # partial derivative of b
m_gradient += pm * 2 / N
b_gradient += pb * 2 / N
print('%11s' % pm, '%11s' % m_gradient, '%11s' % pb, '%11s' % b_gradient)
self.m -= self.learning_rate * m_gradient # adjust current m
self.b -= self.learning_rate * b_gradient # adjust current b
print("Values after: m =", self.m, " b =", self.b)
print()
def fit(self, x_values, y_values): # equivalent to train_model
for i in range(self.iterations):
self.step_gradient(x_values, y_values)
return
def predict(self, x_values): # equivalent to get_output
predictions = []
for x in x_values.ix[:, 0]:
predictions.append(self.get_y(x))
return predictions
I watched Siraj Raval's How to do Linear Regression the right way and followed almost the same way he did. I did learn what partial derivatives and gradient descents are, but I do not what the values of partial derivatives be (or to guess them). And the numbers are going like crazy in the first iteration itself:
Values before: m = 0 b = 0
d(m) m_gradient d(b) b_gradient
150.6325 4.85911290323 -44.5 -1.43548387097
7.44 5.09911290323 -15.5 -1.93548387097
10.935 5.45185483871 -8.1 -2.19677419355
196695.0 6350.45185484 -423.0 -15.8419354839
4341.435 6490.49814516 -119.5 -19.6967741935
3180.9 6593.10782258 -115.0 -23.4064516129
1456.306 6640.08543548 -98.2 -26.5741935484
5.72 6640.26995161 -5.5 -26.7516129032
243.02 6648.10930645 -58.0 -28.6225806452
2.72 6648.19704839 -6.4 -28.8290322581
0.404 6648.21008065 -4.0 -28.9580645161
5.244 6648.37924194 -5.7 -29.1419354839
6.6 6648.59214516 -6.6 -29.3548387097
0.0007 6648.59216774 -0.14 -29.3593548387
0.06 6648.59410323 -1.0 -29.3916129032
37.8 6649.81345806 -10.8 -29.74
24.6 6650.60700645 -12.3 -30.1367741935
10.71 6650.95249032 -6.3 -30.34
11723841.0 384839.371845 -4603.0 -178.823870968
0.0069 384839.372068 -0.3 -178.833548387
78394.9 387368.23981 -419.0 -192.349677419
341255.0 398376.465616 -655.0 -213.478709677
2.7475 398376.554245 -3.5 -213.591612903
1150.0 398413.651019 -115.0 -217.301290323
84.48 398416.376181 -25.6 -218.127096774
1.0 398416.408439 -5.0 -218.288387097
24.675 398417.204406 -17.5 -218.852903226
359720.0 410021.075374 -680.0 -240.788387097
84042.0 412732.107632 -406.0 -253.88516129
27625.0 413623.236665 -325.0 -264.369032258
9.225 413623.534245 -12.3 -264.765806452
81840.0 416263.534245 -1320.0 -307.346451613
38007648.0 1642316.69554 -5712.0 -491.604516129
13.65 1642317.13586 -3.9 -491.730322581
1217.2 1642356.40037 -179.0 -497.504516129
1960.0 1642419.62618 -56.0 -499.310967742
68.85 1642421.84715 -17.0 -499.859354839
0.12 1642421.85102 -1.0 -499.891612903
0.0092 1642421.85132 -0.4 -499.904516129
0.0025 1642421.8514 -0.25 -499.912580645
17.5 1642422.41591 -12.5 -500.315806452
122500.0 1646374.02882 -490.0 -516.122258065
30.25 1646375.00462 -12.1 -516.512580645
9712.5 1646688.31107 -175.0 -522.157741935
15700.0 1647194.76269 -157.0 -527.222258065
22950.4 1647935.09817 -440.0 -541.415806452
1893.725 1647996.18607 -179.5 -547.206129032
1.32 1647996.22865 -2.4 -547.283548387
4860.0 1648153.00285 -81.0 -549.896451613
75.6 1648155.44156 -21.0 -550.573870968
168.0896 1648160.8638 -39.2 -551.838387097
0.532 1648160.88096 -1.9 -551.899677419
0.09 1648160.88387 -1.2 -551.938387097
0.366 1648160.89567 -3.0 -552.03516129
0.01584 1648160.89619 -0.33 -552.045806452
34560.0 1649275.73489 -180.0 -557.852258065
75.0 1649278.15425 -25.0 -558.658709677
27040.0 1650150.41231 -169.0 -564.110322581
2.34 1650150.4878 -2.6 -564.194193548
18.468 1650151.08354 -11.4 -564.561935484
0.26 1650151.09193 -2.5 -564.642580645
213.444 1650157.97722 -50.4 -566.268387097
Values after: m = -165.015797722 b = 0.0566268387097
Values after 10 iteration: m = -1.76899770934e+22 b = 4.21166966984e+18
How do I rightly do LinearRegression from scratch?
This might not be a true answer as it's using R (I could probably figure this out in python, but it would take me longer). I think your issue is in the size of your learning_rate. I'm taking this machine learning class at the moment and so I'm familiar with what you're doing and attempted to implement it myself. Here was my code:
library(ggplot2)
## create test data
data <- data.frame(x = 1:10, y = 1:10)
n <- nrow(data)
## initialize values
m <- 0
b <- 0
alpha <- 0.01
iters <- 100
results <- data.frame(i = 1:iters,
pm = 1:iters,
pb = 1:iters,
m = 1:iters,
b = 1:iters)
for (i in 1:iters) {
y_hat <- (m * data$x) + b
pm <- (1/n) * sum((y_hat - data$y) * data$x)
pb <- (1/n) * sum(y_hat - data$y)
m <- m - (alpha * pm)
b <- b - (alpha * pb)
## uncomment if you want; shows "animated" change
## p <- ggplot(data, aes(x = x, y = y)) + geom_point()
## p <- p + geom_abline(intercept = b, slope = m)
## print(p)
## this turned out to be key for looking at output
results[i, 2:5] <- c(pm, pb, m, b)
}
Now, note the end of results with a big alpha, 0.1:
> tail(results)
i pm pb m b
95 95 -2.864612e+45 -4.114745e+44 2.135518e+44 3.067470e+43
96 96 8.390457e+45 1.205210e+45 -6.254938e+44 -8.984628e+43
97 97 -2.457567e+46 -3.530062e+45 1.832073e+45 2.631600e+44
98 98 7.198218e+46 1.033956e+46 -5.366146e+45 -7.707961e+44
99 99 -2.108360e+47 -3.028460e+46 1.571745e+46 2.257664e+45
100 100 6.175391e+47 8.870365e+46 -4.603646e+46 -6.612702e+45
See how m and b are flip flopping? The learning rate alpha is so high that alpha * derivative are jumping over the minima! In the linked class this is shown in the gradient descent videos, but the concept is the same as this image I found:
Look at results using alpha = 0.01:
> tail(results)
i pm pb m b
95 95 -0.003483741 0.02425319 0.9834438 0.1152615
96 96 -0.003476426 0.02420226 0.9834785 0.1150195
97 97 -0.003469127 0.02415144 0.9835132 0.1147780
98 98 -0.003461842 0.02410073 0.9835478 0.1145370
99 99 -0.003454573 0.02405012 0.9835824 0.1142965
100 100 -0.003447319 0.02399962 0.9836169 0.1140565
It's slow, but we're honing in on m = 1 and b = 0 as expected. With your real data, I had a similar issue. The main code body is the same, with this replacing the data <- data.frame() line at the beginning:
data <- read.table(file = "https://raw.githubusercontent.com/llSourcell/linear_regression_demo/master/brain_body.txt",
header = T, sep = "", stringsAsFactors = F)
names(data) <- c("y", "x")
Everything else is the same, except that I played with alpha and iters. Here's what I found!
## your learning rate; diverging/flip-flopping
## alpha <- 0.0001
> tail(results)
i pm pb m b
95 95 -3.842565e+190 -1.167811e+187 3.801319e+186 1.155276e+183
96 96 3.541406e+192 1.076285e+189 -3.503393e+188 -1.064732e+185
97 97 -3.263851e+194 -9.919315e+190 3.228817e+190 9.812842e+186
98 98 3.008048e+196 9.141894e+192 -2.975760e+192 -9.043766e+188
99 99 -2.772294e+198 -8.425404e+194 2.742537e+194 8.334966e+190
100 100 2.555018e+200 7.765068e+196 -2.527592e+196 -7.681718e+192
## 1/10 as big; still diverging!
## alpha <- 0.00001
> tail(results)
i pm pb m b
95 95 -2.453089e+92 -7.455293e+88 2.189776e+87 6.655047e+83
96 96 2.040052e+93 6.200012e+89 -1.821074e+88 -5.534508e+84
97 97 -1.696559e+94 -5.156089e+90 1.514452e+89 4.602638e+85
98 98 1.410902e+95 4.287936e+91 -1.259457e+90 -3.827672e+86
99 99 -1.173342e+96 -3.565957e+92 1.047397e+91 3.183190e+87
100 100 9.757815e+96 2.965541e+93 -8.710418e+91 -2.647222e+88
## even smaller; that's better!
## alpha <- 0.000001
> tail(results)
i pm pb m b
95 95 -0.01579109 51.95899 0.8856351 -0.004667159
96 96 -0.01579107 51.95894 0.8856352 -0.004719118
97 97 -0.01579106 51.95889 0.8856352 -0.004771077
98 98 -0.01579104 51.95885 0.8856352 -0.004823036
99 99 -0.01579103 51.95880 0.8856352 -0.004874995
100 100 -0.01579102 51.95875 0.8856352 -0.004926953
With this final result, I plotted the results which look reasonable?
p <- ggplot(data, aes(x = x, y = y)) + geom_point()
p <- p + geom_abline(intercept = b, slope = m)
print(p)
So, to wrap up:
I didn't verify/check your python code
I did implement my understanding of gradient descent in R and try with a test to verify behavior
I re-tried this with your actual data to find it appears to work
thus, my recommendation would be to re-try your method with simplified data (sounds like you already might have) and then look at the initial steps with a very small learning rate to see if that fixes it. If not, there may still be something wrong with your math?
Hope that helps!
I want to plot the integration results as described below , but it seems turned out to be a blank sheet, what' s the reason ? please help me!
# -*- coding: utf-8 -*-
import matplotlib.pylab as plt
import numpy as np
import scipy as sp
from scipy.integrate import quad, dblquad, tplquad
x = np.arange(0,1,0.1)
print ("x = ", x)
def f(x):
return x
print ("f(x) = ", f(x))
x_lower = 0
for x_upper in x :
val, abserr = quad(f, x_lower, x_upper)
print ("integral value =", val, ", x_upper = ", x_upper ,", absolute error =", abserr)
plt.plot(x_upper, val, ' b--' )
plt.show()
The output, but plot is blank!
x = [ 0. 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9]
f(x) = [ 0. 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9]
integral value = 0.0 , x_upper = 0.0 , absolute error = 0.0
integral value = 0.005000000000000001 , x_upper = 0.1 , absolute error = 5.551115123125784e-17
integral value = 0.020000000000000004 , x_upper = 0.2 , absolute error = 2.2204460492503136e-16
integral value = 0.04500000000000001 , x_upper = 0.3 , absolute error = 4.996003610813205e-16
integral value = 0.08000000000000002 , x_upper = 0.4 , absolute error = 8.881784197001254e-16
integral value = 0.125 , x_upper = 0.5 , absolute error = 1.3877787807814457e-15
integral value = 0.18000000000000005 , x_upper = 0.6 , absolute error = 1.998401444325282e-15
integral value = 0.24500000000000005 , x_upper = 0.7 , absolute error = 2.720046410331634e-15
integral value = 0.32000000000000006 , x_upper = 0.8 , absolute error = 3.552713678800502e-15
integral value = 0.40499999999999997 , x_upper = 0.9 , absolute error = 4.496403249731884e-15
The reason you do not see anything in the plot is that you are plotting several line plots of only one single point. Since lines would need a start and and end (meaning at least two points) the graph stays blank.
The easiest way of showing your points would be to replace ' b--' in your call to plt.plot() by marker="o":
plt.plot(x_upper, val, marker="o", color="b")
A different option is to first collect all the integration results in a list, and then plot the complete list in a line plot:
import matplotlib.pylab as plt
import numpy as np
from scipy.integrate import quad
x = np.arange(0,1,0.1)
def f(x):
return x
x_lower = 0
vals = []
for x_upper in x :
val, abserr = quad(f, x_lower, x_upper)
vals.append(val)
plt.plot(x, vals, "b--")
plt.show()
I find the answer perhaps, for each time you plot only one dot, but not lines . If you set 'bs' ,then you find it really not a blank, but some dots.
Say, I have a dictionary
D = {'A':0.25,'C':0.25,'G':0.25,'T':0.25}
The sum of dictionary values will always be one. I want to make range for each keys in D that would be as follows:
The first key : (0, D[FirstKey]).
The second key (SecondRangeParameterOfFirstKey, SecondRangeParameterOfFirstKey + ValueOfSecondKey) that is (0.25,0.50).
The third key would be as ( SecondRangeParameterOfSecondKey,SecondRangeParameterOfSecondKey + ValueOfSecondKey) that is (0.50,0.75).
The range for the fourth key would be (0.75,1).
One thing is last parameter of range for last key will always be 1 that is the summation of all values together.
I generate a random float between 0 and 1. I need to return the key following random float . So for example, for the given order of dictionary D, if I generate 0.63 then I have to return third key that is G because its range is (0.50,0.75). As dictionary is not ordered so I have to count range following dictionary's order and return that return the key following order of dictionary. So far I coded for this problem as following:
import random
def W(D):
vv = 0
f = 0
mer = ''
ran = random.uniform(0,1)
DI = D.items()
for k,v in DI:
mer = ''
if (ran >= f) and (ran < D[k]+vv):
mer = k
vv += v
return mer
My function never returns the third key when floats are generated that fall in third keys range that is (0.50,0.75), it returns fourth key instead.
Dicts are unordered so if you want maintain some order you will need an OrderedDict, this will find the key in the range based on increasing ranges on key order, this requires you to add the keys ordered by value:
from collections import OrderedDict
od = OrderedDict((('A', 0.25), ('C', 0.25), ('G',0.25), ('T', 0.25)))
def W(od):
ran = random.uniform(0, 1)
tot = 0
for k, v in od.items():
if tot <= ran < v + tot:
return k
tot += v
Adding a print(ran, v, tot + v) in the loop:
In [36]: W(od)
0.13237220509287917 0.25 0.25
Out[36]: 'A'
In [37]: W(od)
0.22239648741773488 0.25 0.25
Out[37]: 'A'
In [38]: W(od)
0.2798873944681526 0.25 0.25
0.2798873944681526 0.25 0.5
Out[38]: 'C'
In [39]: W(od)
0.05933372630532163 0.25 0.25
Out[39]: 'A'
In [40]: W(od)
0.776438095223963 0.25 0.25
0.776438095223963 0.25 0.5
0.776438095223963 0.25 0.75
0.776438095223963 0.25 1.0
Out[40]: 'T'
If the values are not all the same you will need to sort, you can use operator.itemgetter as the key to sort the items by value:
from operator import itemgetter
d = {'A': 0.35, 'C': 0.2, 'T': 0.3, 'G': 0.15}
def W(d):
ran = random.uniform(0, 1)
tot = 0
# sort from lowest value to highest
for k, v in sorted(d.items(),key=itemgetter(1)):
if tot <= ran < v + tot:
return k
tot += v
Adding a print again:
In [55]: W(d)
0.15 0.24005200696606188 0.15
0.2 0.24005200696606188 0.35
Out[55]: 'C'
In [56]: W(d)
0.15 0.9860872247496385 0.15
0.2 0.9860872247496385 0.35
0.3 0.9860872247496385 0.6499999999999999
0.35 0.9860872247496385 0.9999999999999999
Out[56]: 'A'
In [57]: W(d)
0.15 0.5690026436736583 0.15
0.2 0.5690026436736583 0.35
0.3 0.5690026436736583 0.6499999999999999
Out[57]: 'T'
In [58]: W(d)
0.15 0.28507671431234327 0.15
0.2 0.28507671431234327 0.35
Out[58]: 'C'