# What loss function does the 'multinomial' distribution with the gbm package in R use?

All distributions in the gbm package in R are associated with a loss function. For example, when we set distribution = 'binomial', the loss function chosen internally is the logistic loss function. Can anyone explain how multi-class classification works with gbm and the loss function that is being used for it i.e. when we set distribution='multinomial'? Is it using one-vs-all or all-vs-all under the hood for doing its multi-class classification?

Here is the relevant source code. I'm pretty sure it's using cross-entropy for multiclass:

    //  GBM by Greg Ridgeway  Copyright (C) 2003

#include "multinomial.h"

CMultinomial::CMultinomial(int cNumClasses, int cRows)
{
mcNumClasses = cNumClasses;
mcRows = cRows;

madProb = new double[cNumClasses * cRows];
}

CMultinomial::~CMultinomial()
{
{
}
}

GBMRESULT CMultinomial::UpdateParams
(
unsigned long cLength
)
{
// Local variables
unsigned long ii=0;
unsigned long kk=0;

// Set the probabilities for each observation in each class
for (ii = 0; ii < mcRows; ii++)
{
double dClassSum = 0.0;
for (kk = 0; kk < mcNumClasses; kk++)
{
int iIdx = ii + kk * mcRows;
}

dClassSum = (dClassSum > 0) ? dClassSum : 1e-8;

for (kk = 0; kk < mcNumClasses; kk++)
{
madProb[ii + kk * mcRows] /= dClassSum;
}
}

return GBM_OK;
}

GBMRESULT CMultinomial::ComputeWorkingResponse
(
bool *afInBag,
unsigned long nTrain,
int cIdxOff
)
{
unsigned long i = 0;

for(i=cIdxOff; i<nTrain+cIdxOff; i++)
{
}

return GBM_OK;
}

GBMRESULT CMultinomial::InitF
(
double &dInitF,
unsigned long cLength
)
{
dInitF = 0.0;
return GBM_OK;
}

double CMultinomial::Deviance
(
unsigned long cLength,
int cIdxOff
)
{
unsigned long ii=0;
double dL = 0.0;
double dW = 0.0;

for(ii=cIdxOff; ii<cLength+cIdxOff; ii++)
{
}

return dL/dW;
}

GBMRESULT CMultinomial::FitBestConstant
(
unsigned long *aiNodeAssign,
unsigned long nTrain,
VEC_P_NODETERMINAL vecpTermNodes,
unsigned long cTermNodes,
unsigned long cMinObsInNode,
bool *afInBag,
int cIdxOff
)
{
// Local variables
GBMRESULT hr = GBM_OK;
unsigned long iNode = 0;
unsigned long iObs = 0;

// Call LocM for the array of values on each node
for(iNode=0; iNode<cTermNodes; iNode++)
{
if(vecpTermNodes[iNode]->cN >= cMinObsInNode)
{
// Get the number of nodes here
double dNum = 0.0;
double dDenom = 0.0;
for (iObs = 0; iObs < nTrain; iObs++)
{
if(afInBag[iObs] && (aiNodeAssign[iObs] == iNode))
{
int iIdx = iObs + cIdxOff;
}
}

dDenom = (dDenom > 0) ? dDenom : 1e-8;

vecpTermNodes[iNode]->dPrediction = dNum / dDenom;
}
}

return hr;
}

double CMultinomial::BagImprovement
(
bool *afInBag,
double dStepSize,
unsigned long nTrain
)
{
double dReturnValue = 0.0;
double dW = 0.0;

unsigned long ii;
unsigned long kk;

// Calculate the probabilities after the step
double *adStepProb = new double[mcNumClasses * mcRows];

// Assume that this is last class - calculate new prob as in updateParams but
// using (F_ik + ss*Fadj_ik) instead of F_ik. Then calculate OOB improve
for (ii = 0; ii < mcRows; ii++)
{
double dClassSum = 0.0;
for (kk = 0; kk < mcNumClasses; kk++)
{
int iIdx = ii + kk * mcRows;
}

dClassSum = (dClassSum > 0) ? dClassSum : 1e-8;

for (kk = 0; kk < mcNumClasses; kk++)
{
adStepProb[ii + kk * mcRows] /= dClassSum;
}
}

// Calculate the improvement
for(ii=0; ii<nTrain; ii++)
{
if(!afInBag[ii])
{
for (kk = 0; kk < mcNumClasses; kk++)
{
int iIdx = ii + kk * mcRows;