Classifying Data with Neural Networks
Classifying Data with Neural Networks
makeCluster[class_, μ_, ρ_] := RandomVariate[MultinormalDistribution[μ, {{1, 2ρ}, {2ρ, 4}}], 600] -> class;clusters = makeCluster@@@{{Red, {1.5, 1.5}, -.2}, {Green, {-1.5, 1}, .1}, {Blue, {0, -2.5}, .8}};plot = ListPlot[Keys[clusters], PlotStyle -> {RGBColor[0.8, 0., 0.], RGBColor[0., 0.8, 0.], RGBColor[0., 0., 0.8]}, AspectRatio -> 1, Frame -> True, PlotRange -> {{-5, 5}, {-5, 5}}]trainingData = Flatten[Thread /@ clusters];
RandomSample[trainingData, 6]Create a net to compute the probability of a point lying in each cluster, using a "Class" decoder to classify the input as Red, Green or Blue:
net = NetChain[{LinearLayer[30], ElementwiseLayer[Ramp], LinearLayer[3], SoftmaxLayer[]}, "Input" -> {2}, "Output" -> NetDecoder[{"Class", {Red, Green, Blue}}]]results = NetTrain[net, trainingData, All]
trained = results["TrainedNet"]trained[{{1.5, 1}, {-1.5, 1}, {0, -3}}]Show[plot, Quiet@Table[ContourPlot[trained[{x, y}, "Probabilities" -> color] == 0.75, {x, -5, 5}, {y, -5, 5}, ContourStyle -> {Thick, Darker[color, .3]}], {color, {Red, Green, Blue}}]]Plot the degree of uncertainty of the classifier as measured by entropy as a function of the position:
ArrayPlot[Table[trained[{x, y}, "Entropy"], {y, 5, -4, -.1}, {x, -4, 4, .1}]]trainingData = ExampleData[{"MachineLearning", "FisherIris"}, "TrainingData"];
testData = ExampleData[{"MachineLearning", "FisherIris"}, "TestData"];RandomSample[trainingData, 5]labels = Union[Values[trainingData]]Create a NetChain to perform the classification, using a "Class" decoder to interpret the output of the net as probabilities for each class:
net = NetChain[{3, SoftmaxLayer[]}, "Input" -> 4, "Output" -> NetDecoder[{"Class", labels}]]NetTrain will automatically use a CrossEntropyLossLayer with a NetEncoder to interpret the class labels in the training data:
results = NetTrain[net, trainingData, All]
trained = results["TrainedNet"]trained[{6.1, 2.8, 4., 1.3}]trained[{6.1, 2.8, 4., 1.3}, "Probabilities"]Use NetMeasurements to test the classification performance of the trained net on the test set:
NetMeasurements[trained, testData, "Accuracy"]NetMeasurements[trained, testData, "ConfusionMatrixPlot"]data = ExampleData[{"Dataset", "Titanic"}];
data = DeleteMissing[data, 1, 2]{trainingData, testData} = TakeDrop[RandomSample[data], 800];classEncoder = NetEncoder[{"Class", {"1st", "2nd", "3rd"}, "UnitVector"}]
genderEncoder = NetEncoder[{"Class", {"male", "female"}, "UnitVector"}]classEncoder /@ {"1st", "2nd", "3rd"}genderEncoder /@ {"male", "female"}Create a network with an input corresponding to each feature and using a "Boolean" decoder to interpret the output of the net as the probability of survival.
net = NetGraph[{CatenateLayer[], LinearLayer[], LogisticSigmoid, ReshapeLayer[{1}]}, {NetPort["age"] -> 4, {NetPort["class"], 4, NetPort["sex"]} -> 1, 1 -> 2 -> 3 -> NetPort["survived"]}, "class" -> classEncoder, "sex" -> genderEncoder, "survived" -> "Boolean"]trainingData[[1]]Train the net on the training data. NetTrain will automatically attach a CrossEntropyLossLayer["Binary"] layer to the output of the net:
results = NetTrain[net, trainingData, All, MaxTrainingRounds -> 1000]
trained = results["TrainedNet"]trained[<|"class" -> "2nd", "age" -> 24, "sex" -> "female"|>]trained[<|"class" -> "2nd", "age" -> 24, "sex" -> "female"|>, None]p[class_, age_, sex_] := trained[<|"class" -> class, "age" -> age, "sex" -> sex|>, None];Plot[{p["1st", x, "female"], p["3rd", x, "female"], p["1st", x, "male"], p["3rd", x, "male"]}, {x, 0, 100}, PlotLegends -> {"female, 1st class", "female, 3rd class", "male, 1st class", "male, 3rd class"}, Frame -> True, FrameLabel -> {"age (years)", "survival probability"}]Use NetMeasurements to test the accuracy of the trained net on the test set:
NetMeasurements[trained, testData, "Accuracy"]The accuracy is typically comparable to that obtained using Classify when specifying the method "LogisticRegression":
cf = Classify[trainingData -> "survived", Method -> "LogisticRegression"];
ClassifierMeasurements[cf, testData -> "survived", "Accuracy"]obj = ResourceObject["CIFAR-100"]trainingData = ResourceData[obj, "TrainingDataset"];
RandomSample[trainingData, 5]labels = Union@Normal@trainingData[All, "Label"]sublabels = Union@Normal@trainingData[All, "SubLabel"]convnet = NetChain[{
ConvolutionLayer[20, {5, 5}],
ElementwiseLayer[Ramp],
PoolingLayer[{2, 2}, {2, 2}],
ConvolutionLayer[50, {5, 5}],
ElementwiseLayer[Ramp],
PoolingLayer[{2, 2}, {2, 2}],
FlattenLayer[],
LinearLayer[500],
ElementwiseLayer[Ramp]
}, "Input" -> NetEncoder[{"Image", {32, 32}}]]Create a NetGraph that will produce separate classifications for the high-level and low-level labels:
net = NetGraph[{convnet, 100, SoftmaxLayer[], 20, SoftmaxLayer[]}, {NetPort["Image"] -> 1 -> 2 -> 3 -> NetPort["SubLabel"], 2 -> 4 -> 5 -> NetPort["Label"]},
"Label" -> NetDecoder[{"Class", labels}], "SubLabel" -> NetDecoder[{"Class", sublabels}]]Train the network. NetTrain will automatically attach CrossEntropyLossLayer objects to both outputs, taking the target values from the training data using the corresponding names "Label" and "SubLabel":
results = NetTrain[net, trainingData, All, MaxTrainingRounds -> 10]
trained = results["TrainedNet"]trained[[image]]trained[{[image], [image], [image], [image], [image]}, NetPort@"SubLabel"]trained[[image], NetPort@"SubLabel" -> {"TopProbabilities", 3}]From a random sample, select the images for which the net produces highest and lowest entropy predictions for "Label":
images = RandomSample[Normal[trainingData][[All, "Image"]], 5000];entropies = trained[images, NetPort@"Label" -> "Entropy"];Labeled[images[[Ordering[entropies, -10]]], "high entropy"]
Labeled[images[[Ordering[entropies, 10]]], "low entropy"]Use NetMeasurements to test the accuracy for both outputs of the net:
NetMeasurements[trained, trainingData, {<|"Measurement" -> "Accuracy", "Source" -> "Label", "Key" -> "Acc1"|>, <|"Measurement" -> "Accuracy", "Source" -> "SubLabel", "Key" -> "Acc2"|>}]subnet = Take[trained, {NetPort["Image"], NetPort["SubLabel"]}]subnet[[image]]