Beta Regression
You could use beta-regression. I have no practical experience with this type of regression. However, it might be the right method for your task. As far as I understand, the link function is chosen so to restrict $\hat{y} \in [0,1]$.
Here is an R implementation, where the docs say:
Fit beta regression models for rates and proportions via maximum
likelihood using a parametrization with mean (depending through a link
function on the covariates) and precision parameter (called phi).
Example:
library("betareg")
data("GasolineYield", package = "betareg")
summary(GasolineYield$yield)
Min. 1st Qu. Median Mean 3rd Qu. Max.
0.0280 0.1165 0.1780 0.1966 0.2705 0.4570
br = betareg(yield ~ batch + temp, data = GasolineYield)
preds = predict(br, newdata=GasolineYield)
summary(preds)
Min. 1st Qu. Median Mean 3rd Qu. Max.
0.04571 0.10309 0.16364 0.19655 0.26429 0.50792
Regression Models For Ordinal Data
Ordinal Logistic Regression could be used for this problem since classes are ordered and multinomial classification does not take the order of classes into consideration. In practice, this algorithm doesn't scale to many classes or many observations because its computationally expensive.
Here is an example of fitting a cumulative link model (CLM) such as the proportional odds model to data using the ordinal package in R.
require("ordinal")
fm1 <- clm(rating ~ contact + temp, data=wine)
summary(fm1)
formula: rating ~ contact + temp
data: wine
link threshold nobs logLik AIC niter max.grad cond.H
logit flexible 72 -86.49 184.98 6(0) 4.01e-12 2.7e+01
Coefficients:
Estimate Std. Error z value Pr(>|z|)
contactyes 1.5278 0.4766 3.205 0.00135 **
tempwarm 2.5031 0.5287 4.735 2.19e-06 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Threshold coefficients:
Estimate Std. Error z value
1|2 -1.3444 0.5171 -2.600
2|3 1.2508 0.4379 2.857
3|4 3.4669 0.5978 5.800
4|5 5.0064 0.7309 6.850
Regression with a Logistic Link Function
As suggested by Ben Reiniger in the comments of the question, another alternative is simply to use a Logistic Link function in a regression model.
An example would be using xgboost with reg:logistic as the objective function. However, many libraries may not support this behavior as they need the target be either one or zero.