This is probably not the answer you're looking for, but I ended up copying the code from TryGetScoreLabelNames (it's in the Legacy namespace as of 0.7) and tweaking it to use the schema from my input data. The dataView below is an IDataView I created from my prediction input data so I could get the schema off of it.
public bool TryGetScoreLabelNames(out string[] names, string scoreColumnName = DefaultColumnNames.Score)
{
names = (string[])null;
Schema outputSchema = model.GetOutputSchema(dataView.Schema);
int col = -1;
if (!outputSchema.TryGetColumnIndex(scoreColumnName, out col))
return false;
int valueCount = outputSchema.GetColumnType(col).ValueCount;
if (!outputSchema.HasSlotNames(col, valueCount))
return false;
VBuffer<ReadOnlyMemory<char>> vbuffer = new VBuffer<ReadOnlyMemory<char>>();
outputSchema.GetMetadata<VBuffer<ReadOnlyMemory<char>>>("SlotNames", col, ref vbuffer);
if (vbuffer.Length != valueCount)
return false;
names = new string[valueCount];
int num = 0;
foreach (ReadOnlyMemory<char> denseValue in vbuffer.DenseValues())
names[num++] = denseValue.ToString();
return true;
}
I also asked this question in gitter for ml.net (https://gitter.im/dotnet/mlnet) and got this response from Zruty0
my best suggestion is to convert labels to 0..(N-1) beforehand, then
train, and then inspect the resulting 'Score' column. It'll be a
vector of size N, with per-class scores. PredictedLabel is actually
just argmax(Score), and you can get the 2nd and other candidates by
sorting Score
If you have a static set of classes this might be a better option, but my situation has an ever-growing set of classes.
ValueCount
will be gone in 0.8 so you'll have to cast((VectorType)col).Size
instead. – Pearlstein