Recall from nltk.metrics.score returning None - nltk

I'm trying to calculate the precision and recall using the nltk.metrics.score (http://www.nltk.org/_modules/nltk/metrics/scores.html) with my NLTK.NaiveBayesClassifier.
However, I stumble upon the error:
"unsupported operand type(s) for +: 'int' and 'NoneType".
which I suspect is from my 10-fold cross-validation where in some reference sets, there are zero negative (the data set is a bit imbalanced where 87% of it is positive).
According to nltk.metrics.score,
def precision(reference, test):
"Given a set of reference values and a set of test values, return
the fraction of test values that appear in the reference set.
In particular, return card(``reference`` intersection
``test``)/card(``test``).
If ``test`` is empty, then return None."
It seems that some of my 10-fold set is returning recall as None since there are no Negative in the reference set. Any idea on how to approach this problem?
My full code is as follow:
trainfeats = negfeats + posfeats
n = 10 # 5-fold cross-validation
subset_size = len(trainfeats) // n
accuracy = []
pos_precision = []
pos_recall = []
neg_precision = []
neg_recall = []
pos_fmeasure = []
neg_fmeasure = []
cv_count = 1
for i in range(n):
testing_this_round = trainfeats[i*subset_size:][:subset_size]
training_this_round = trainfeats[:i*subset_size] + trainfeats[(i+1)*subset_size:]
classifier = NaiveBayesClassifier.train(training_this_round)
refsets = collections.defaultdict(set)
testsets = collections.defaultdict(set)
for i, (feats, label) in enumerate(testing_this_round):
refsets[label].add(i)
observed = classifier.classify(feats)
testsets[observed].add(i)
cv_accuracy = nltk.classify.util.accuracy(classifier, testing_this_round)
cv_pos_precision = precision(refsets['Positive'], testsets['Positive'])
cv_pos_recall = recall(refsets['Positive'], testsets['Positive'])
cv_pos_fmeasure = f_measure(refsets['Positive'], testsets['Positive'])
cv_neg_precision = precision(refsets['Negative'], testsets['Negative'])
cv_neg_recall = recall(refsets['Negative'], testsets['Negative'])
cv_neg_fmeasure = f_measure(refsets['Negative'], testsets['Negative'])
accuracy.append(cv_accuracy)
pos_precision.append(cv_pos_precision)
pos_recall.append(cv_pos_recall)
neg_precision.append(cv_neg_precision)
neg_recall.append(cv_neg_recall)
pos_fmeasure.append(cv_pos_fmeasure)
neg_fmeasure.append(cv_neg_fmeasure)
cv_count += 1
print('---------------------------------------')
print('N-FOLD CROSS VALIDATION RESULT ' + '(' + 'Naive Bayes' + ')')
print('---------------------------------------')
print('accuracy:', sum(accuracy) / n)
print('precision', (sum(pos_precision)/n + sum(neg_precision)/n) / 2)
print('recall', (sum(pos_recall)/n + sum(neg_recall)/n) / 2)
print('f-measure', (sum(pos_fmeasure)/n + sum(neg_fmeasure)/n) / 2)
print('')

Perhaps not the most elegant, but guess the most simple fix would be setting it to 0 and the actual value if not None, e.g.:
cv_pos_precision = 0
if precision(refsets['Positive'], testsets['Positive']):
cv_pos_precision = precision(refsets['Positive'], testsets['Positive'])
And for the others as well, of course.

Related

mlogit error: (Error in model.frame.default(terms(formula, lhs = lhs, rhs = rhs, data = data, : variable lengths differ (found for 'OSTAN1'))

I have collected data from a survey in order to perform a choice based conjoint analysis. I have preprocessed and clean data. However, when I apply the function mlogit on the dataset I get the following error:
Error in model.frame.default(terms(formula, lhs = lhs, rhs = rhs, data = data, : variable lengths differ (found for 'OSTAN1')
while I omitted 'OSTAN1'variable, the same error happened for the next variable and so on.
I really do not understand why. Can please some one help me to understand what I am doing wrong ?
library("mlogit")
data("DATA3", package = "mlogit")
Electr <- dfidx(DATA3, idx = list(c("chid", "ID")),
choice = "NOE_TASADOF", varying = 2:10, sep = "")
Elec.mxl <- mlogit(NOE_TASADOF ~ TIME + WEEKEND + NOR + HAVA + GHANON +
KHASTEGI + GOVAHINAME + TAHSILAT+ OSTAN1 + OSTAN2+ OSTAN3+ AGE1+ AGE2+AGE3+ FASL1+
FASL2+FASL3+FASL4|0,
rpar=c(OSTAN1 = 'n', OSTAN2 = 'n',
OSTAN3='n', AGE1='n', AGE2='n',
AGE3='n', TIME='n',WEEKEND='n',
NOR='n',HAVA='n', GHANON='n',KHASTEGI='n',
GOVAHINAME='n', TAHSILAT='n') ,R = 100, correlation = FALSE,halton = NA, Electr , panel = TRUE)

Double pendulum animation in python

I am using the following code to solve the system of differential equations numerically and then animate it:
for i in range(steps-1):
Theta1 = t1[i]
Theta2 = t2[i]
dTheta1 = w1[i]
dTheta2 = w2[i]
a1 = (g*(np.sin(Theta2)*np.cos(Theta1-Theta2)-mu*np.sin(Theta1))-(l2*dTheta2*dTheta2+l1*dTheta1*dTheta1*np.cos(Theta1-Theta2))*np.sin(Theta1-Theta2))/(l1*(mu-np.cos(Theta1-Theta2)*np.cos(Theta1-Theta2)))
a2 = (mu*g*(np.sin(Theta1)*np.cos(Theta1-Theta2)-np.sin(Theta2))+(mu*l1*dTheta1*dTheta1+l2*dTheta2*dTheta2*np.cos(Theta1-Theta2))*np.sin(Theta1-Theta2))/(l2*(mu-np.cos(Theta1-Theta2)*np.cos(Theta1-Theta2)))
w1[i+1] = w1[i] + dt*a1
w2[i+1] = w2[i] + dt*a2
t1[i+1] = t1[i] + dt*w1[i]
t2[i+1] = t2[i] + dt*w2[i]
This gives me errors such as
RuntimeWarning: invalid value encountered in longdouble_scalars
and
RuntimeWarning: overflow encountered in longdouble_scalars.
At first, I thought this might be happening due to precisions errors, so I tried using longdouble. But that didn't help at all. When I run the animation, I get a few frames of unphysical systems and then it shuts downs. I have checked my equation from multiple sources and I ended up using their equations too and the problem still persists. What am I doing wrong?
Edit: Okay so simply decreasing the step size seemed to not give me the error any more, but now animation is unphysical. The pendulum seems to pick up speed over time, and also performs full rotations, even when it started from rest at an extreme. I am using a 4th order RK method and still getting this problem. Any ideas? I have provided my new code below
def diff_eq_a1(theta1,theta2,w1,w2):
a11 = mu
a12 = np.cos(theta1-theta2)
a21 = np.cos(theta1-theta2)
a22 = 1
b1 = (mu*g*l1*np.sin(theta1)) + (l2*np.sin(theta1-theta2)*w2*w2)
b2 = (g*l2*np.sin(theta2))-(l1*np.sin(theta1-theta2)*w1*w1)
return -(1/l1)*(b1*a22-b2*a12)/(a11*a22-a21*a12)
def diff_eq_a2(theta1,theta2,w1,w2):
a11 = mu
a12 = np.cos(theta1-theta2)
a21 = np.cos(theta1-theta2)
a22 = 1
b1 = (mu*g*l1*np.sin(theta1)) + (l2*np.sin(theta1-theta2)*w2*w2)
b2 = (g*l2*np.sin(theta2))-(l1*np.sin(theta1-theta2)*w1*w1)
return -(1/l2)*(b2*a11-b1*a21)/(a11*a22-a21*a12)
for i in range(steps-1):
a1_k1 = dt*diff_eq_a1(t1[i],t2[i],w1[i],w2[i])
a1_k2 = dt*diff_eq_a1((t1[i]+0.5*a1_k1),t2[i],w1[i],w2[i])
a1_k3 = dt*diff_eq_a1((t1[i]+0.5*a1_k2),t2[i],w1[i],w2[i])
a1_k4 = dt*diff_eq_a1((t1[i]+a1_k3),t2[i],w1[i],w2[i])
w1[i+1] = w1[i] + (a1_k1/6)+(a1_k2/3)+(a1_k3/3)+(a1_k4/6)
a2_k1 = dt*diff_eq_a1(t1[i],t2[i],w1[i],w2[i])
a2_k2 = dt*diff_eq_a1(t1[i],(t2[i]+0.5*a2_k1),w1[i],w2[i])
a2_k3 = dt*diff_eq_a1(t1[i],(t2[i]+0.5*a2_k2),w1[i],w2[i])
a2_k4 = dt*diff_eq_a1(t1[i],(t2[i]+a2_k3),w1[i],w2[i])
w2[i+1] = w2[i] + (a2_k1/6)+(a2_k2/3)+(a2_k3/3)+(a2_k4/6)
t1[i+1] = t1[i] + dt*w1[i]
t2[i+1] = t2[i] + dt*w2[i]
x1 = l1*np.sin(t1)
x2 = x1 + l2*np.sin(t2)
y1 = - l1*np.cos(t1)
y2 = y1 - l2*np.cos(t2)
I know its not very neat right now, but I really just want to get it working first

Can prefix beam search commonly used in speech recognition with CTC be implemented in such a simpler way?

I am learning about speech recognition recently, and I have learned that the idea of prefix beam search is to merge paths with the same prefix, such as [1,1,_] and [_,1,_] (as you can see, _ indicates blank mark).
Based on this understanding, I implemented a version of mine, which can be simplified using pseudo code like this:
def prefix_beam_search(y, beam_size, blank):
seq_len, n_class = y.shape
logY = np.log(y)
beam = [([], 0)]
for t in range(seq_len):
buff = []
for prefix, p in beam:
for i in range(n_class):
new_prefix = list(prefix) + [i]
new_p = p + logY[t][i]
buff.append((new_prefix, new_p))
# merge the paths with same prefix'
new_beam = defaultdict(lambda: ninf)
for prefix, p in buff:
# 'norm_prefix' can simplify the path, [1,1,_,2] ==> [1,2]
# However, the ending 'blank' is retained, [1,1,_] ==> [1,_]
prefix = norm_prefix(prefix, blank)
new_beam[prefix] = logsumexp(new_beam[prefix], p)
# choose the best paths
new_beam = sorted(new_beam.items(), key=lambda x: x[1], reverse=True)
beam = new_beam[: beam_size]
return beam
But most of the versions I found online (according to the paper) are like this:
def _prefix_beam_decode(y, beam_size, blank):
T, V = y.shape
log_y = np.log(y)
beam = [(tuple(), (0, ninf))]
for t in range(T):
new_beam = defaultdict(lambda: (ninf, ninf))
for prefix, (p_b, p_nb) in beam:
for i in range(V):
p = log_y[t, i]
if i == blank:
new_p_b, new_p_nb = new_beam[prefix]
new_p_b = logsumexp(new_p_b, p_b + p, p_nb + p)
new_beam[prefix] = (new_p_b, new_p_nb)
continue
end_t = prefix[-1] if prefix else None
new_prefix = prefix + (i,)
new_p_b, new_p_nb = new_beam[new_prefix]
if i != end_t:
new_p_nb = logsumexp(new_p_nb, p_b + p, p_nb + p)
else:
new_p_nb = logsumexp(new_p_nb, p_b + p)
new_beam[new_prefix] = (new_p_b, new_p_nb)
if i == end_t:
new_p_b, new_p_nb = new_beam[prefix]
new_p_nb = logsumexp(new_p_nb, p_nb + p)
new_beam[prefix] = (new_p_b, new_p_nb)
beam = sorted(new_beam.items(), key=lambda x: logsumexp(*x[1]), reverse=True)
beam = beam[:beam_size]
return beam
The results of the two are different, and my version tends to return longer strings. And I don't quite understand the main two aspects:
Are there any details of my version that are not thoughtful?
The common version while generate new prefix by new_prefix = prefix + (i,) regardless of whether the end of the previous are the same as the given 's'. For example, the old prefix is [a,a,b] and when a new character s is added, both [a,a,b] and [a,a,b,b] are saved. What is the purpose if this? And does it cause double counting?
Looking forward to your answer, thanks in advance!
When you choose the best paths in your code, you don't want to differentiate between [1,_] and [1] since both correspond to the same prefix [1].
If you have for example:
[1], [1,_], [1,2]
then you want the probability of [1] and [1,_] both to have the sum of the two.
probability([1]) = probability([1])+probability([1,_])
probability([1,_]) = probability([1])+probability([1,_])
And after sorting with these probabilities, you may want to keep so many that the number of true prefixes is beam_size.
For example, you have [1], [1,_], [2], [3].
Of which probabilities are: 0.1, 0.08, 0.11, 0.15
Then the probabilities with which you want to sort them are:
0.18, 0.18, 0.11, 0.15, respectively (0.18 = 0.1 + 0.08)
Sorted: [1]:0.18, [1,_]: 0.18, [3]:0.15, [2]:0.11
And if you have beam_size 2, for example, then you may want to keep
[1], [1,_] and [3] so that you have 2 prefixes in your beam, because [1] and [1,_] count as the same prefix (as long as the next character is not 1 - that's why we keep track of [1] and [1,_] separately).

Object of type 'closure' is not subsettable - R

I am using R to extract tweets and analyse their sentiment, however when I get to the lines below I get an error saying "Object of type 'closure' is not subsettable"
scores$drink = factor(rep(c("east"), nd))
scores$very.pos = as.numeric(scores$score >= 2)
scores$very.neg = as.numeric(scores$score <= -2)
Full code pasted below
load("twitCred.Rdata")
east_tweets <- filterStream("tweetselnd.json", locations = c(-0.10444, 51.408699, 0.33403, 51.64661),timeout = 120, oauth = twitCred)
tweets.df <- parseTweets("tweetselnd.json", verbose = FALSE)
##function score.sentiment
score.sentiment = function(sentences, pos.words, neg.words, .progress='none')
{
# Parameters
# sentences: vector of text to score
# pos.words: vector of words of postive sentiment
# neg.words: vector of words of negative sentiment
# .progress: passed to laply() to control of progress bar
scores = laply(sentences,
function(sentence, pos.words, neg.words)
{
# remove punctuation
sentence = gsub("[[:punct:]]", "", sentence)
# remove control characters
sentence = gsub("[[:cntrl:]]", "", sentence)
# remove digits?
sentence = gsub('\\d+', '', sentence)
# define error handling function when trying tolower
tryTolower = function(x)
{
# create missing value
y = NA
# tryCatch error
try_error = tryCatch(tolower(x), error=function(e) e)
# if not an error
if (!inherits(try_error, "error"))
y = tolower(x)
# result
return(y)
}
# use tryTolower with sapply
sentence = sapply(sentence, tryTolower)
# split sentence into words with str_split (stringr package)
word.list = str_split(sentence, "\\s+")
words = unlist(word.list)
# compare words to the dictionaries of positive & negative terms
pos.matches = match(words, pos.words)
neg.matches = match(words, neg.words)
# get the position of the matched term or NA
# we just want a TRUE/FALSE
pos.matches = !is.na(pos.matches)
neg.matches = !is.na(neg.matches)
# final score
score = sum(pos.matches) - sum(neg.matches)
return(score)
}, pos.words, neg.words, .progress=.progress )
# data frame with scores for each sentence
scores.df = data.frame(text=sentences, score=scores)
return(scores.df)
}
pos = readLines(file.choose())
neg = readLines(file.choose())
east_text = sapply(east_tweets, function(x) x$getText())
scores = score.sentiment(tweetseldn.json, pos, neg, .progress='text')
scores()$drink = factor(rep(c("east"), nd))
scores()$very.pos = as.numeric(scores()$score >= 2)
scores$very.neg = as.numeric(scores$score <= -2)
# how many very positives and very negatives
numpos = sum(scores$very.pos)
numneg = sum(scores$very.neg)
# global score
global_score = round( 100 * numpos / (numpos + numneg) )
If anyone could help with as to why I'm getting this error it will be much appreciated. Also I've seen other answeres about adding '()' when referring to the variable 'scores' such as scores()$.... but it hasn't worked for me. Thank you.
The changes below got rid of the error:
x <- scores
x$drink = factor(rep(c("east"), nd))
x$very.pos = as.numeric(x$score >= 2)
x$very.neg = as.numeric(x$score <= -2)

Plotting a function in matlab involving an integral

I'm trying to plot a function that contains a definite integral. My code uses all anonymous functions. When I run the file, it gives me an error. My code is below:
%%% List of Parameters %%%
gamma_sp = 1;
cap_gamma = 15;
gamma_ph = 0;
omega_0 = -750;
d_omega_0 = 400;
omega_inh = 100;
d_omega_inh = 1000;
%%% Formulae %%%
gamma_t = gamma_sp/2 + cap_gamma/2 + gamma_ph;
G = #(x) exp(-(x-omega_inh).^2./(2*d_omega_inh.^2))./(sqrt(2*pi)*d_omega_inh);
F = #(x) exp(-(x-omega_0).^2./(2*d_omega_0.^2))./(sqrt(2*pi)*d_omega_0);
A_integral = #(x,y) G(x)./(y - x + 1i*gamma_t);
Q_integral = #(x,y) F(x)./(y - x + 1i*gamma_t);
A = #(y) integral(#(x)A_integral(x,y),-1000,1000);
Q = #(y) integral(#(x)Q_integral(x,y),-3000,0);
P1 = #(y) -1./(1i.*(gamma_sp + cap_gamma)).*(1./(y + 2.*1i.*gamma_t)*(A(y)-conj(A(0)))-1./y.*(A(y)-A(0))+cap_gamma./gamma_sp.*Q(y).*(A(0)-conj(A(0))));
P2 = #(y) conj(P1(y));
P = #(y) P1(y) - P2(y);
sig = #(y) abs(P(y)).^2;
rng = -2000:0.05:1000;
plot(rng,sig(rng))
It seems to me that when the program runs the plot command, it should put each value of rng into sig(y), and that value will be used as the y value in A_integral and Q_integral. However, matlab throws an error when I try to run the program.
Error using -
Matrix dimensions must agree.
Error in #(x,y)G(x)./(y-x+1i*gamma_t)
Error in #(x)A_integral(x,y)
Error in integralCalc/iterateScalarValued (line 314)
fx = FUN(t);
Error in integralCalc/vadapt (line 133)
[q,errbnd] = iterateScalarValued(u,tinterval,pathlen);
Error in integralCalc (line 76)
[q,errbnd] = vadapt(#AtoBInvTransform,interval);
Error in integral (line 89)
Q = integralCalc(fun,a,b,opstruct);
Error in #(y)integral(#(x)A_integral(x,y),-1000,1000)
Error in
#(y)-1./(1i.*(gamma_sp+cap_gamma)).*(1./(y+2.*1i.*gamma_t)*(A(y)-conj(A(0)))-1. /y.*(A(y)-A(0))+cap_gamma./gamma_sp.*Q(y).*(A(0)-conj(A(0))))
Error in #(y)P1(y)-P2(y)
Error in #(y)abs(P(y)).^2
Error in fwm_spec_diff_paper_eqn (line 26)
plot(rng,sig(rng))
Any ideas about what I'm doing wrong?
You have
>> rng = -2000:0.05:1000;
>> numel(rng)
ans =
60001
all 60001 elements get passed down to
A = #(y) integral(#(x)A_integral(x,y),-1000,1000);
which calls
A_integral = #(x,y) G(x)./(y - x + 1i*gamma_t);
(similar for Q). The thing is, integral is an adaptive quadrature method, meaning (roughly) that the amount of x's it will insert into A_integral varies with how A_integral behaves at certain x.
Therefore, the amount of elements in y will generally be different from the elements in x in the call to A_integral. This is why y-x +1i*gamma_t fails.
Considering the complexity of what you're trying to do, I think it is best to re-define all anonymous functions as proper functions, and integrate a few of them into single functions. Look into the documentation of bsxfun to see if that can help (e.g., bsxfun(#minus, y.', x) instead of y-x could perhaps fix a few of these issues), otherwise, vectorize only in x and loop over y.
Thanks Rody, that made sense to me. I keep trying to use matlab like mathematica and I forget how matlab does things. I modified the code a bit, and it produces the right result. The integrals are evaluated very roughly, but it should be easy to fix that. I've posted my modified code below.
%%% List of Parameters %%%
gamma_sp = 1;
cap_gamma = 15;
gamma_ph = 0;
omega_0 = -750;
d_omega_0 = 400;
omega_inh = 100;
d_omega_inh = 1000;
%%% Formulae %%%
gamma_t = gamma_sp/2 + cap_gamma/2 + gamma_ph;
G = #(x) exp(-(x-omega_inh).^2./(2*d_omega_inh.^2))./(sqrt(2*pi)*d_omega_inh);
F = #(x) exp(-(x-omega_0).^2./(2*d_omega_0.^2))./(sqrt(2*pi)*d_omega_0);
A_integral = #(x,y) G(x)./(y - x + 1i*gamma_t);
Q_integral = #(x,y) F(x)./(y - x + 1i*gamma_t);
w = -2000:0.05:1000;
sigplot = zeros(size(w));
P1plot = zeros(size(w));
P2plot = zeros(size(w));
Pplot = zeros(size(w));
aInt_range = -1000:0.1:1200;
qInt_range = -2000:0.1:100;
A_0 = sum(A_integral(aInt_range,0).*0.1);
for k=1:size(w,2)
P1plot(k) = -1./(1i*(gamma_sp + cap_gamma)).*(1./(w(k)+2.*1i.*gamma_t).*(sum(A_integral(aInt_range,w(k)).*0.1)-conj(A_0))-1./w(k).*(sum(A_integral(aInt_range,w(k)).*0.1)-A_0)+cap_gamma./gamma_sp.*sum(Q_integral(qInt_range,w(k)).*0.1).*(A_0-conj(A_0)));
P2plot(k) = conj(P1plot(k));
Pplot(k) = P1plot(k) - P2plot(k);
sigplot(k) = abs(Pplot(k)).^2;
end
plot(w,sigplot)