@@ -51,6 +51,7 @@ function nlreg(@nospecialize(df),
5151 dof_add:: Integer = 0 ,
5252 save:: Vector{Symbol} = Symbol[],
5353 method:: Symbol = :cpu ,
54+ nthreads:: Integer = method == :cpu ? Threads. nthreads () : 256 ,
5455 drop_singletons = true ,
5556 double_precision:: Bool = true ,
5657 dev_tol:: Real = 1.0e-8 , # tolerance level for the first stopping condition of the maximization routine.
@@ -83,6 +84,11 @@ function nlreg(@nospecialize(df),
8384 subset = eval (evaluate_subset (df, subsetformula))
8485 end
8586
87+ if method == :cpu && nthreads > Threads. nthreads ()
88+ @warn " Keyword argument nthreads = $(nthreads) is ignored (Julia was started with only $(Threads. nthreads ()) threads)."
89+ nthreads = Threads. nthreads ()
90+ end
91+
8692 # #############################################################################
8793 # #
8894 # # Parse formula
@@ -157,6 +163,8 @@ function nlreg(@nospecialize(df),
157163 @info " $(dropped_n) observations detected as singletons. Dropping them ..."
158164 end
159165 end
166+ else
167+ error (" No fixed effect specified. Use GLM.jl for the estimation of generalized linear models without fixed effects." )
160168 end
161169
162170 save_fe = (:fe ∈ save) & has_fes
@@ -263,7 +271,7 @@ function nlreg(@nospecialize(df),
263271 Xexo, basecoef = detect_linear_dependency_among_X! (Xexo, basecoef; coefnames= coef_names)
264272
265273 weights = Weights (Ones {Float64} (sum (esample)))
266- feM = AbstractFixedEffectSolver {double_precision ? Float64 : Float32} (fes, weights, Val{method})
274+ feM = AbstractFixedEffectSolver {double_precision ? Float64 : Float32} (fes, weights, Val{method}, nthreads )
267275
268276 # make one copy after deleting NAs + dropping singletons + detecting separations (fe + relu)
269277 nobs = sum (esample)
@@ -283,24 +291,25 @@ function nlreg(@nospecialize(df),
283291 (length (start) == coeflength) || error (" Invalid length of `start` argument." )
284292 beta = start
285293 else
286- beta = 0.1 .* ones (Float64, coeflength)
294+ # beta = zeros(double_precision ? Float64 : Float32, coeflength)
295+ beta = 0.1 .* ones (double_precision ? Float64 : Float32, coeflength)
287296 end
288297
289298 # Xexo = oldX[esample,:]
290299 Xexo = GLFixedEffectModels. getcols (Xexo, basecoef) # get Xexo from oldX and basecoef and esample
291300
292301 eta = Xexo * beta
293302 mu = GLM. linkinv .(Ref (link),eta)
294- wt = ones (Float64, nobs, 1 )
303+ wt = ones (double_precision ? Float64 : Float32 , nobs, 1 )
295304 dev = sum (devresid .(Ref (distribution), y, mu))
296305 nulldev = sum (devresid .(Ref (distribution), mean (y), mu))
297306
298307 Xhat = Xexo
299- crossx = Matrix {Float64} (undef, nobs, 0 )
308+ crossx = Matrix {double_precision ? Float64 : Float32 } (undef, nobs, 0 )
300309 residuals = y[:] # just for initialization
301310
302311 # Stuff that we need in outside scope
303- emp = Array {Float64,2} (undef,2 ,2 )
312+ emp = Array {double_precision ? Float64 : Float32 ,2} (undef,2 ,2 )
304313 score = hessian = emp
305314
306315 outer_iterations = 0
@@ -439,6 +448,11 @@ function nlreg(@nospecialize(df),
439448 display (Xdemean .* nudemean)
440449 display (Xhat .* nu)
441450 end
451+
452+ # if dev > nulldev
453+ # @warn "Final deviance exceeds null deviance. Possibly running into a local maximum. Try restarting with a different starting guess."
454+ # end
455+
442456 break
443457 else
444458 verbose && println (" Iter $i : not converged. Δdev = $((devold - dev)/ dev) , ||Δβ|| = $(norm (beta_update)) " )
@@ -463,7 +477,7 @@ function nlreg(@nospecialize(df),
463477 augmentdf = DataFrame ()
464478 if save_residuals
465479 if nobs < length (esample)
466- augmentdf. residuals = Vector {Union{Float64, Missing}} (missing , length (esample))
480+ augmentdf. residuals = Vector {Union{double_precision ? Float64 : Float32 , Missing}} (missing , length (esample))
467481 augmentdf[esample, :residuals ] = residuals
468482 else
469483 augmentdf[! , :residuals ] = residuals
@@ -473,12 +487,15 @@ function nlreg(@nospecialize(df),
473487 oldX = oldX[esample,:]
474488 oldX = getcols (oldX, basecoef)
475489 # update FixedEffectSolver
476- weights = Weights (Ones {Float64} (sum (esample)))
490+ weights = Weights (Ones {double_precision ? Float64 : Float32 } (sum (esample)))
477491 feM = AbstractFixedEffectSolver {double_precision ? Float64 : Float32} (fes, weights, Val{method})
478492 newfes, b, c = solve_coefficients! (eta - oldX * coef, feM; tol = center_tol, maxiter = maxiter_center)
493+ for fekey in fekeys
494+ augmentdf[! , fekey] = df[:, fekey]
495+ end
479496 for j in 1 : length (fes)
480497 if nobs < length (esample)
481- augmentdf[! , ids[j]] = Vector {Union{Float64, Missing}} (missing , length (esample))
498+ augmentdf[! , ids[j]] = Vector {Union{double_precision ? Float64 : Float32 , Missing}} (missing , length (esample))
482499 augmentdf[esample, ids[j]] = newfes[j]
483500 else
484501 augmentdf[! , ids[j]] = newfes[j]
@@ -487,15 +504,15 @@ function nlreg(@nospecialize(df),
487504 end
488505 if :mu ∈ save
489506 if nobs < length (esample)
490- augmentdf. mu = Vector {Union{Float64, Missing}} (missing , length (esample))
507+ augmentdf. mu = Vector {Union{double_precision ? Float64 : Float32 , Missing}} (missing , length (esample))
491508 augmentdf[esample, :mu ] = mu
492509 else
493510 augmentdf[! , :mu ] = mu
494511 end
495512 end
496513 if :eta ∈ save
497514 if nobs < length (esample)
498- augmentdf. eta = Vector {Union{Float64, Missing}} (missing , length (esample))
515+ augmentdf. eta = Vector {Union{double_precision ? Float64 : Float32 , Missing}} (missing , length (esample))
499516 augmentdf[esample, :eta ] = eta
500517 else
501518 augmentdf[! , :eta ] = eta
@@ -589,6 +606,7 @@ function nlreg(@nospecialize(df),
589606 outer_converged,
590607 esample,
591608 augmentdf,
609+ fekeys,
592610 ll,
593611 null_ll,
594612 distribution,
0 commit comments