Accord.net: Multilabel classification issue - c#

I am trying to upgrade my code for multi-label classification from version 3.0.2. to 3.3.0. I did the upgrade, but it seems that classification results were much worse now - algorithm is not able to classify many more instances than before. Can you please tell me if there is any issue in my new code. How to use estimated parameters for gauss kernel as I did before?
Old code:
var gauss = Gaussian.Estimate(inputs, Convert.ToInt32(inputs.GetLength(0) * 0.8));
// Create the machine.
this.machine = new MultilabelSupportVectorMachine(inputs[0].Length, gauss, outputs[0].Length);
// Train the model.
var teacher = new MultilabelSupportVectorLearning(this.machine, inputs, outputs);
teacher.Algorithm = (svm, classInputs, classOutputs, i, j) => new SequentialMinimalOptimization(svm, classInputs, classOutputs) { UseComplexityHeuristic = true, CacheSize = 1000 };
teacher.SubproblemFinished += SubproblemFinished;
var error = teacher.Run(true);
// Save the model.
this.machine.Save(modelPath);
New code:
var gauss = Gaussian.Estimate(inputs, Convert.ToInt32(inputs.GetLength(0) * 0.8));
// Create the machine.
this.machine = new MultilabelSupportVectorMachine<Gaussian>(inputs[0].Length, gauss, outputs[0].Length);
// Create the multi-class learning algorithm for the machine
var teacher = new MultilabelSupportVectorLearning<Gaussian>(this.machine)
{
// Configure the learning algorithm to use SMO to train the
// underlying SVMs in each of the binary class subproblems.
Learner = (param) => new SequentialMinimalOptimization<Gaussian>()
{
// Estimate a suitable guess for the Gaussian kernel's parameters.
// This estimate can serve as a starting point for a grid search.
UseKernelEstimation = true,
UseComplexityHeuristic = true,
CacheSize = 1000
}
};
teacher.ParallelOptions.MaxDegreeOfParallelism = 1;
// Learn a machine
machine = teacher.Learn(inputs, outputs);
Serializer.Save(machine, modelPath);
Thanks in advance!

Related

Wordcloud Highcharts .NET

I am having an issue with the creation of a Wordcloud with Highcharts 7.1.2 with C# and .NET.
I can create the wordcloud just fine, but I can't set the weight of the words.
The piece of code below is what I currently have, as you can see I am trying to use the Labelrank as a mean to set the weight. I cannot find an example of the wordcloud in c#, but I found some in JS and they always set the weight of each word.
List<Series> seriesList = new List<Series>();
List<WordcloudSeriesData> newWordcloudSeriesDataList = new List<WordcloudSeriesData>();
foreach (var data in datas)
{
newWordcloudSeriesDataList.Add(new WordcloudSeriesData
{
Name = data.Name,
Labelrank = data.Rank
});
}
seriesList.Add(new WordcloudSeries
{
Data = newWordcloudSeriesDataList,
Rotation = new WordcloudSeriesRotation
{
From = 0,
To = 0,
Orientations = 1
}
});
PS: I found a workaround.
When you create the json before sending it to the front, use
chartinfo = chartinfo.Replace("labelrank", "weight");
where chartinfo is the json.

Guide to use Yolo with gpu c#

I've been trying to find a tutorial or something on how to make yolo c# use gpu instead of cpu, I always find that it says that it works on both cpu and gpu but no one ever says how to use the gpu since it always uses cpu for me. Here's my code with yolo v5 c#. It doesn't really matter for me if it uses yolo v5 just that it uses gpu. Tutorial I found that tutorial but i can't even find the download for Nvidia cuDNN v7.6.3 for CUDA 10.1. It feels very unclear on how to use it with gpu please help me :D
var image = pictureBox1.Image;
var scorer = new YoloScorer<YoloCocoP5Model>("Assets/Weights/yolov5n.onnx");
List<YoloPrediction> predictions = scorer.Predict(image);
var graphics = Graphics.FromImage(image);
foreach (var prediction in predictions) // iterate predictions to draw results
{
using (MemoryStream ms = new MemoryStream())
{
pictureBox1.Image.Save(ms, ImageFormat.Png);
prediction.Label.Color = Color.FromArgb(255, 255, 0, 0);
double score = Math.Round(prediction.Score, 2);
graphics.DrawRectangles(new Pen(prediction.Label.Color, 1),
new[] { prediction.Rectangle });
var (x, y) = (prediction.Rectangle.X - 3, prediction.Rectangle.Y - 23);
graphics.DrawString($"{prediction.Label.Name} ({score})",
new Font("Consolas", 16, GraphicsUnit.Pixel), new SolidBrush(prediction.Label.Color),
new PointF(x, y));
pictureBox1.Image = image;
}
}
Before you are going to use scorer you need an option set.
//https://onnxruntime.ai/docs/execution-providers/CUDA-ExecutionProvider.html
bool initResult = false;
var cudaProviderOptions = new Microsoft.ML.OnnxRuntime.OrtCUDAProviderOptions(); // Dispose this finally
var providerOptionsDict = new Dictionary<string, string>();
providerOptionsDict["device_id"] = "0";
providerOptionsDict["gpu_mem_limit"] = "2147483648";
providerOptionsDict["arena_extend_strategy"] = "kSameAsRequested";
/*
cudnn_conv_algo_search
The type of search done for cuDNN convolution algorithms.
Value Description
EXHAUSTIVE (0) expensive exhaustive benchmarking using cudnnFindConvolutionForwardAlgorithmEx
HEURISTIC (1) lightweight heuristic based search using cudnnGetConvolutionForwardAlgorithm_v7
DEFAULT (2) default algorithm using CUDNN_CONVOLUTION_FWD_ALGO_IMPLICIT_PRECOMP_GEMM
Default value: EXHAUSTIVE
*/
providerOptionsDict["cudnn_conv_algo_search"] = "DEFAULT";
/*
do_copy_in_default_stream
Whether to do copies in the default stream or use separate streams. The recommended setting is true. If false, there are race conditions and possibly better performance.
Default value: true
*/
providerOptionsDict["do_copy_in_default_stream"] = "1";
/*
cudnn_conv_use_max_workspace
Check tuning performance for convolution heavy models for details on what this flag does. This flag is only supported from the V2 version of the provider options struct when used using the C API. The V2 provider options struct can be created using this and updated using this. Please take a look at the sample below for an example.
Default value: 0
*/
providerOptionsDict["cudnn_conv_use_max_workspace"] = "1";
/*
cudnn_conv1d_pad_to_nc1d
Check convolution input padding in the CUDA EP for details on what this flag does. This flag is only supported from the V2 version of the provider options struct when used using the C API. The V2 provider options struct can be created using this and updated using this. Please take a look at the sample below for an example.
Default value: 0
*/
providerOptionsDict["cudnn_conv1d_pad_to_nc1d"] = "1";
cudaProviderOptions.UpdateOptions(providerOptionsDict);
options = SessionOptions.MakeSessionOptionWithCudaProvider(cudaProviderOptions); // Dispose this finally
if (options != null)
{
// check yolo model file is accesible
if (File.Exists(yoloModelFile))
{
scorer = new YoloScorer<YoloCocoP5Model>(yoloModelFile, options);
initResult = true;
}
else
{
DebugMessage("Yolo model ONNX file (" + yoloModelFile + ") is missing!\r\n", 2);
}
}
else
DebugMessage("Yolo instance initializing error! Session options are empty!\r\n", 2);
}

How to create a TensorProto in c#?

This is a snipped of the c# client I created to query the tensorflow server I set up using this tutorial: https://tensorflow.github.io/serving/serving_inception.html
var channel = new Channel("TFServer:9000", ChannelCredentials.Insecure);
var request = new PredictRequest();
request.ModelSpec = new ModelSpec();
request.ModelSpec.Name = "inception";
var imgBuffer = File.ReadAllBytes(#"sample.jpg");
ByteString jpeg = ByteString.CopyFrom(imgBuffer, 0, imgBuffer.Length);
var jpgeproto = new TensorProto();
jpgeproto.StringVal.Add(jpeg);
jpgeproto.Dtype = DataType.DtStringRef;
request.Inputs.Add("images", jpgeproto); // new TensorProto{TensorContent = jpeg});
PredictionClient client = new PredictionClient(channel);
I found out that most classes needed to be generated from proto files using protoc
The only thing which I cant find is how to construct the TensorProto. The error I keep getting is : Additional information: Status(StatusCode=InvalidArgument, Detail="tensor parsing error: images")
There is a sample client (https://github.com/tensorflow/serving/blob/master/tensorflow_serving/example/inception_client.py) byt my Python skills are not sufficient to understand the last bit.
I also implemented that client in another language (Java).
Try to change
jpgeproto.Dtype = DataType.DtStringRef;
to
jpgeproto.Dtype = DataType.DtString;
You may also need to add a tensor shape with a dimension to your tensor proto. Here's my working solution in Java, should be similar in C#:
TensorShapeProto.Dim dim = TensorShapeProto.Dim.newBuilder().setSize(1).build();
TensorShapeProto shape = TensorShapeProto.newBuilder().addDim(dim).build();
TensorProto proto = TensorProto.newBuilder()
.addStringVal(ByteString.copyFrom(imageBytes))
.setTensorShape(shape)
.setDtype(DataType.DT_STRING)
.build();
ModelSpec spec = ModelSpec.newBuilder().setName("inception").build();
PredictRequest r = PredictRequest.newBuilder()
.setModelSpec(spec)
.putInputs("images", proto).build();
PredictResponse response = blockingStub.predict(r);

Store Kinect's v2.0 Motion to BVH File

I would like to store the motion capture data from Kinect 2 as a BVH file. I found code which does so for Kinect 1 which can be found here. I went through the code and found several things that I was not able to understand.
For example, in the mentioned code I've tried to understand what exactly the Skeleton skel object, found in several places in the code, actually is. If not, are there any known application available to accomplish the intended?
EDIT: I tried to change Skeleton skel to Body skel which I think is the correspondant object for kinect SDK 2.0. However I've got an error when I try to get the position of the body:
tempMotionVektor[0] = -Math.Round( skel.Position.X * 100,2);
tempMotionVektor[1] = Math.Round( skel.Position.Y * 100,2) + 120;
tempMotionVektor[2] = 300 - Math.Round( skel.Position.Z * 100,2);
I've gotten errors when calling the function Position for the Body skel. How can I retrieve the X, Y, Z of the skeleton in sdk 2.0?? I tried to change the above three lines to:
tempMotionVektor[0] = -Math.Round(skel.Joints[0].Position.X * 100, 2);
tempMotionVektor[1] = Math.Round(skel.Joints[0].Position.Y * 100, 2) + 120;
tempMotionVektor[2] = 300 - Math.Round(skel.Joints[0].Position.Z * 100, 2);
EDIT: Basically I managed to store the a bvh file after combining bodyBasicsWPF and kinect2bvh. However, it seems that the skeleton I am storing is not efficient. There are strange movements in the elbows. I am trying to understand if I have to change something in the file kinectSkeletonBVH.cp. More specifically, what are the changes in the joint axis orientation for the kinect 2 version. How can I change the following line: skel.BoneOrientations[JointType.ShoulderCenter].AbsoluteRotation.Quaternion; I tried to change that line with skel.JointOrientations[JointType.ShoulderCenter].Orientation. Am I right? I am using the following code to add the joint to BVHBone objects:
BVHBone hipCenter = new BVHBone(null, JointType.SpineBase.ToString(), 6, TransAxis.None, true);
BVHBone hipCenter2 = new BVHBone(hipCenter, "HipCenter2", 3, TransAxis.Y, false);
BVHBone spine = new BVHBone(hipCenter2, JointType.SpineMid.ToString(), 3, TransAxis.Y, true);
BVHBone shoulderCenter = new BVHBone(spine, JointType.SpineShoulder.ToString(), 3, TransAxis.Y, true);
BVHBone collarLeft = new BVHBone(shoulderCenter, "CollarLeft", 3, TransAxis.X, false);
BVHBone shoulderLeft = new BVHBone(collarLeft, JointType.ShoulderLeft.ToString(), 3, TransAxis.X, true);
BVHBone elbowLeft = new BVHBone(shoulderLeft, JointType.ElbowLeft.ToString(), 3, TransAxis.X, true);
BVHBone wristLeft = new BVHBone(elbowLeft, JointType.WristLeft.ToString(), 3, TransAxis.X, true);
BVHBone handLeft = new BVHBone(wristLeft, JointType.HandLeft.ToString(), 0, TransAxis.X, true);
BVHBone neck = new BVHBone(shoulderCenter, "Neck", 3, TransAxis.Y, false);
BVHBone head = new BVHBone(neck, JointType.Head.ToString(), 3, TransAxis.Y, true);
BVHBone headtop = new BVHBone(head, "Headtop", 0, TransAxis.None, false);
I can't understand where inside the code the axis for every Joint is calculated.
The code you used for Kinect 1.0 to obtain a BVH file use the joints information to build bone vectors by reading the Skeleton.
public static double[] getBoneVectorOutofJointPosition(BVHBone bvhBone, Skeleton skel)
{
double[] boneVector = new double[3] { 0, 0, 0 };
double[] boneVectorParent = new double[3] { 0, 0, 0 };
string boneName = bvhBone.Name;
JointType Joint;
if (bvhBone.Root == true)
{
boneVector = new double[3] { 0, 0, 0 };
}
else
{
if (bvhBone.IsKinectJoint == true)
{
Joint = KinectSkeletonBVH.String2JointType(boneName);
boneVector[0] = skel.Joints[Joint].Position.X;
boneVector[1] = skel.Joints[Joint].Position.Y;
boneVector[2] = skel.Joints[Joint].Position.Z;
..
Source: Nguyên Lê Đặng - Kinect2BVH.V2
Except in Kinect 2.0, Skeleton class has been replaced by the Body class, so you need to change it to deal with a Body instead, and obtain the joints by following the steps quoted below.
// Kinect namespace
using Microsoft.Kinect;
// ...
// Kinect sensor and Kinect stream reader objects
KinectSensor _sensor;
MultiSourceFrameReader _reader;
IList<Body> _bodies;
// Kinect sensor initialization
_sensor = KinectSensor.GetDefault();
if (_sensor != null)
{
_sensor.Open();
}
We also added a list of bodies, where all of the body/skeleton related
data will be saved. If you have developed for Kinect version 1, you
notice that the Skeleton class has been replaced by the Body class.
Remember the MultiSourceFrameReader? This class gives us access on
every stream, including the body stream! We simply need to let the
sensor know that we need body tracking functionality by adding an
additional parameter when initializing the reader:
_reader = _sensor.OpenMultiSourceFrameReader(FrameSourceTypes.Color |
FrameSourceTypes.Depth |
FrameSourceTypes.Infrared |
FrameSourceTypes.Body);
_reader.MultiSourceFrameArrived += Reader_MultiSourceFrameArrived;
The Reader_MultiSourceFrameArrived method will be called whenever a
new frame is available. Let’s specify what will happen in terms of the
body data:
Get a reference to the body frame
Check whether the body frame is null – this is crucial
Initialize the _bodies list
Call the GetAndRefreshBodyData method, so as to copy the body data into the list
Loop through the list of bodies and do awesome stuff!
Always remember to check for null values. Kinect provides you with
approximately 30 frames per second – anything could be null or
missing! Here is the code so far:
void Reader_MultiSourceFrameArrived(object sender,
MultiSourceFrameArrivedEventArgs e)
{
var reference = e.FrameReference.AcquireFrame();
// Color
// ...
// Depth
// ...
// Infrared
// ...
// Body
using (var frame = reference.BodyFrameReference.AcquireFrame())
{
if (frame != null)
{
_bodies = new Body[frame.BodyFrameSource.BodyCount];
frame.GetAndRefreshBodyData(_bodies);
foreach (var body in _bodies)
{
if (body != null)
{
// Do something with the body...
}
}
}
}
}
This is it! We now have access to the bodies Kinect identifies. Next
step is to display the skeleton information on-screen. Each body
consists of 25 joints. The sensor provides us with the position (X, Y,
Z) and the rotation information for each one of them. Moreover, Kinect
lets us know whether the joints are tracked, hypothsized or not
tracked. It’s a good practice to check whether a body is tracked
before performing any critical functions.
The following code illustrates how we can access the different body
joints:
if (body != null)
{
if (body.IsTracked)
{
Joint head = body.Joints[JointType.Head];
float x = head.Position.X;
float y = head.Position.Y;
float z = head.Position.Z;
// Draw the joints...
}
}
Source: Vangos Pterneas Blog - KINECT FOR WINDOWS VERSION 2: BODY TRACKING

How do I update a Cloudwatch custom metric in C#?

How do I create a custom metric for my Elastic Beanstalk environment in C#?
I have a numerical metric seconds.
I use the following code:
double seconds = ts.Seconds + (Convert.ToDouble(ts.Milliseconds / 10) / 100);
using (AmazonCloudWatchClient cloudwatch = new AmazonCloudWatchClient(accessKey, secretKey))
{
PutMetricDataRequest mdr = new PutMetricDataRequest();
mdr.Namespace = "Performance";
MetricDatum dataPoint = new MetricDatum();
dataPoint.MetricName = "UploadSpeedInSeconds";
dataPoint.Unit = "Seconds";
dataPoint.Value = seconds;
}
I have no idea were to continue on. I want the custom metric to mesuare the uploads in seconds of files. I already have the metric value, and I want to update a custom metric so I can keep track of it (BTW: can I view the custom metric in the console?).
Don't forget to actually send it off to AWS:
mdr.MetricData = new List<MetricDatum>();
mdr.MetricData.Add(dataPoint);
PutMetricDataResponse resp = cloudwatch.PutMetricData(mdr);
Debug.Assert(resp.HttpStatusCode == System.Net.HttpStatusCode.OK);

Categories