You are now following this question
- You will see updates in your followed content feed.
- You may receive emails, depending on your communication preferences.
I have boundaries of objects in my code. I want to use those boundaries to calculate the features of those objects in my preceding loop. please help fix
2 views (last 30 days)
Show older comments
edges = edge(imgContrast,'Canny');
se = strel('disk', 1);
edgesClean = imclose(edges, se);
edgesClean = imfill(edgesClean, 'holes');
B = bwboundaries(edgesClean);
[X, Y] = meshgrid(1:columns, 1:rows);
areaOfEachZone = zeros(1, numZones);
profileCounts = nan(1, numZones);
totalArea = nan(1, numZones);
avgSize = nan(1, numZones);
zoneArea = nan(1, numZones);
avgCircularity = nan(1, numZones);
avgFeret = nan(1, numZones);
avgMinFeret = nan(1, numZones);
for k = 1:numZones
% Create a binary mask for this zone
zoneMask = (sqrt((X - x).^2 + (Y - y).^2) >= radius(k)) & (sqrt((X - x).^2 + (Y - y).^2) < radius(k+1));
areaOfEachZone(k) = sum(zoneMask, 'all') * pixelSize^2;
% Calculate connected components in this zone
cc = bwconncomp(zoneMask);
% Calculate region properties for each connected component in this zone
statscc = regionprops(cc, 'Area', 'Centroid', 'Eccentricity', 'Perimeter', 'MajorAxisLength', 'MinorAxisLength','Circularity');
% Calculate region properties for each object and store in arrays
% areas = [];
areaOfEachZone = [];
feretDiams = [];
circularities = NaN(size(B,1),1); % initialize circularities array to NaN
for j = 1:size(B,1)
boundary = B{j};
objectMask = poly2mask(boundary(:,2), boundary(:,1), size(AI,1), size(AI,2));
regionProps = regionprops(objectMask, 'Area', 'Perimeter', 'MaxFeretProperties');
% Calculate circularity
if ~isempty(regionProps) && size(regionProps, 1) == 1 && regionProps.Area > 0 % exclude regions with zero area
circularity = 4*pi*regionProps.Area/regionProps.Perimeter^2;
if circularity >= 0 && circularity <= 1 % circularity should be between 0 and 1
circularities(j) = circularity;
else
circularities(j) = NaN;
end
areaOfEachZone(j) = regionProps.Area;
feretDiams(j) = regionProps.MaxFeretDiameter;
else
areaOfEachZone(j) = 0;
circularities(j) = NaN;
feretDiams(j) = 0;
end
end
% Calculate features for this zone
numObjects = cc.NumObjects;
if numObjects > 0
areas = [statscc.Area];
profileCounts(k) = numObjects;
totalArea(k) = sum(areas) * pixelSize^2;
% zoneArea(k) = areaOfEachZone(k);
% Calculate average size of mitochondria for this zone
avgSize(k) = mean(areas) * pixelSize^2;
% circularities = [statscc.Circularity];
avgCircularity(k) = mean(circularities(isfinite(circularities)));
% ferets = [statscc.MajorAxisLength];
feretDiams(j) = regionProps.MaxFeretDiameter;
avgFeret(k) = mean(feretsDiams) * pixelSize;
minFerets = [statscc.MinorAxisLength];
avgMinFeret(k) = mean(minFerets) * pixelSize;
end
end
So I am novice to matlab, some others in the group before me were working on this but left adn now i have to fix some errors i am getting. I run into this wall because the larger loop is supposed to be for a particular area in the image but then i have another loop that indixes for the boundaries found within that area but it never results successfully such that the features within that area with those boundaries are indexed properly. What do you suggest to correct this?
3 Comments
Image Analyst
on 6 Apr 2023
Well for starters, format your code as code with the Code icon
Next attach your original image so I can see if an edge detection is really what you need to do (it rarely is). Then attach the beginning part of your program where you read it in and finally get to where you have imgContrast and the rest of your code continues.
If you have any more questions, then attach your image and code to read it in with the paperclip icon after you read this:
It's a generic, general purpose demo of how to threshold an image to find blobs, and then measure things about the blobs, and extract certain blobs based on their areas or diameters.
Chanille
on 6 Apr 2023
BI = imread(MyRGBImage,1); %%AI channel or (MyRGBImage); for other images
bg = imopen(BI, strel('disk', 25));
imgNoBg = BI - bg;
imgContrast = imadjust(imgNoBg);
I haven't finished the rest of the code because I am trying to fix the above issue but it would be something like this:
%% % Display average region properties for current image
fprintf('Avg Area: %f, Avg Circularity: %f, Avg Feret Diameter: %f, Num Objects: %d\n', ...
avgArea, avgCircularity, avgFeretDiam, numObjects);
Chanille
on 6 Apr 2023
@Image Analyst I still have a question even after reading your really cool demo. How can i ensure that the boundaries detected are what the regionprops is calculating within my for k loop? Thank you! I look forward to contributing to this forum some day. :)
Accepted Answer
Image Analyst
on 6 Apr 2023
You don't need that inside loop over size(B, 1). You can simply get all the values like
% Calculate region properties for each connected component in this zone
statscc = regionprops(cc, 'Area', 'Centroid', 'Eccentricity', 'Perimeter', 'MajorAxisLength', 'MinorAxisLength','Circularity');
meanArea = mean([statscc.Area])
xyCentroids = vertcat(statscc.Centroid); % Not sure what you want to do with these.
meanEccentricity = mean([statscc.Eccentricity])
meanMajorAxisLength = mean([statscc.MajorAxisLength])
meanMinorAxisLength = mean([statscc.MinorAxisLength])
meanCircularity = mean([statscc.Circularity])
% and so on.
52 Comments
Chanille
on 6 Apr 2023
@Image Analyst But don't i need to use B to get all the features of the iamge since B defines the boundaries of each individual small circle? So shouldn't i incorpoarte that into my regionprops somehow?
So my intention is to get a bunch of images and import them with this code. then get all of the objects (the small gray circle blobs) by using edge detection then calculating all of those features aforementioned by using regionnprops. i am not convinced that without B i am measuring the objects accurately because some of the values for circularity are larger than 1! (Which as you may know is physically impossible).
What do you suggest now? Thanks!!
Image Analyst
on 6 Apr 2023
No. You have a zoneMask that you need to multiply by your object mask. Then you pass that into bwconncomp.
objectMask = grayImage > 50; % Whatever.
mask = objectMask & zoneMask;
cc = bwconncomp(mask);
props = regionprops(cc, grayImage, 'Area');
The mask has everything you need to get those shape parameters. There is no need at all to get the boundaries as far as measuring things in the blobs. It's only use, really, is to let you plot a colored outline around each blob. It's not used in measuring anything. So no need to use poyl2mask on each blobs either. regionprops does all that for you.
Chanille
on 7 Apr 2023
I did zoneMask = zoneMask .* im2double(edgesClean) .* DD;
where DD is a binary image made of white pixels that depict the area of interest and black that depict the area i want to ignore. Is this okay @Image Analyst?
Also, I decided to finish the code with:
features(m).filename = allFileNames{m};
features(m).totalArea = totalArea;
features(m).avgSize = avgSize;
features(m).zoneArea = zoneArea;
features(m).AvgCircularityy = avgCircularity;
features(m).AvgFeret = avgFeret;
features(m).AvgMinFeret = avgMinFeret;
features(m).profileCounts = profileCounts;
I had another look at your blobs code but it is not obvious to me how to use the features as a basis to create a code that also measures the features and then is able to determine (based on the stored features above) whether the current image being analyzed belongs to that class of images (shares similar features) or not. How would you suggest that I do this please? Thank you!!
Image Analyst
on 7 Apr 2023
Your statement(s) is/are very vague. Not sure what "use the features as a basis to create a code that also measures the features" means. I don't do that -- use features to measure features. What we do is to use some algorithm to process the image in a way such that you can threshold it to get objects of interest, and background. I call this the mask and this process is called image segmentation. Sometimes you can threshold right away but sometimes you must do something to the image first before you can threshold it. And sometimes after you threshold the blobs in the mask still need some processing to extract only the blobs you're interested in and not the others. After all that is done you will have what we call a "segmented image". You then simply pass it to regionprops to make the measurements you want. Those measurements are often called "features" - things like area, perimeter, mean intensity, etc.
Now to classify your object(s) or image, you must put those features into a classification routine. If you want, you can manually look at the measurements/features and decide on what class, for example look at the area to classify blobs into big blobs and small blobs, or look at circularity to classify into round or non-round blobs. Sometimes it's not so simple like that and you're not sure what features should be compared and how. So in that case, if you have the Statistics and Machine Learning Toolbox you can put all of your features into columns of a table called something like tPredictors, and your "true" classes (known in advance because you have a training set) into the "responses" and use the "Classification Learner" app on the Apps tab of the tool ribbon. It will create a model object (variable) which you can then pass to a function, along with your unknown image, to classify it. There is a field of the trainedModel that will tell you how to classify your image with your new trainedModel.
You did not say what the classes were so I can't help much until you say what classes you want to sort your images into.
Chanille
on 7 Apr 2023
@Image Analyst I will look into this.
The classes are, if i understand correctly, in my case, restricted, non restricted and advanced non restriction. In each case the feature measurements will change.
Chanille
on 7 Apr 2023
@Image Analyst I did look into this. Again, I am a novice so if you could provide some more suggestions like an example of a working classification routine that would be great. But here is what I have determined so far based on your explanation:
% split data into a training set and a validation set, using the "cvpartition" function, a partition object that
% splits your data into 80% training and 20% validation:
cv = cvpartition(numObservations,'HoldOut',0.2);
trainingData = MyData(cv.training,:);
use the "fitcsvm" function to train a support vector machine (SVM) classifier on training data
svmModel = fitcsvm(trainingData,labels);
However, I have no idea how to put this into a working code in terms of what I have above. How would you?
Thank you!
Image Analyst
on 7 Apr 2023
For the classification training you need a set of measurements -- a table with N columns for the N things you measured in each image, and each row is the measurements for that image. So if you have M images you would have a table of M rows and N columns. Next you need to have a vector of "true" ground truth classifications. Then start Classification Learner and specify your training data then specify your model, then click the train button. Then export your model. Attach your table in a .mat file if you need more help.
Image Analyst
on 9 Apr 2023
I meant the code with the fitcsvm in it, not the image analysis program. Anyway this is what I have:
s = load('features.mat')
s = struct with fields:
features: [1×3 struct]
features = s.features
features = 1×3 struct array with fields:
filename
totalArea
avgSize
zoneArea
AvgCircularityy
AvgFeret
AvgMinFeret
profileCounts
tbl = struct2table(features)
tbl = 3×8 table
filename totalArea avgSize zoneArea AvgCircularityy AvgFeret AvgMinFeret profileCounts
____________________________________________________________________________________ ___________ ___________ ___________ _______________ ___________ ___________ _____________
{'1_Merge_WD_M1_12pm_dendra2_actin647_lipitox594.lif - TileScan 1_Merged-2.tif' } 1×12 double 1×12 double 1×12 double 1×12 double 1×12 double 1×12 double 1×12 double
{'2_8bit_Merge_WD_M1_12pm_dend12_actin647_lipitox594.lif - TileScan 1_Merged-2.tif'} 1×12 double 1×12 double 1×12 double 1×12 double 1×12 double 1×12 double 1×12 double
{'3_Merge_WD_M1_12pm_dendra2_actin647_lipitox594.lif - TileScan 1_Merged-2.tif' } 1×12 double 1×12 double 1×12 double 1×12 double 1×12 double 1×12 double 1×12 double
Now, in order to classify that, with fitcsvm or ClassificationLearner, what we need is the "true" classes for each image. Then we need to figure out why there are 12 measurements for each image, and if east set of those has the same class or different classes.
Chanille
on 9 Apr 2023
here is the code although I am not sure if it would work.
The true class for the feature mat I attached is advanced non restriction. I will send the other two classes measured featured mats. if that is what you mean by true classes.
There are 12 measurements because I put 12 zones so i have 12 zones with different measurements of circ, feret, etc. for that measurement (zones can be any number). As long as i set the zones to 12 (or 10, 9) there will be 12 (or 10, 9) measurements in the ground true data used to train the algorithm.
How would i use what you provided to make a working training program?
Ultimately I would be able to feed in an image and the program would say this is advanced non restricted etc. do you ahve a program/demo like that?
Image Analyst
on 9 Apr 2023
Why do you have 12 zones? Is the "true" class for all 12 zones the same class? Or does each zone have a different true class?
Chanille
on 10 Apr 2023
Could you clarify what you mean by "true class"? I believe you're referring to the class that images are classified as. Based on the features I provided, it is an advanced, non-restricted class that consists of 12 zones. The number 12 was chosen because it's my desired number, not because of any empirical reasons. All 12 zones in this class are represented in the same feature matrix file. For unknown class images, another set of 12 zones will be measured. These zones belong to an undetermined class and will be compared to the ground truth 12 zones from the advanced non-restricted class for classification purposes.
Image Analyst
on 10 Apr 2023
If you're going to train a classifier, you have to have some images that have known classes, like class A, class B, and Class C or whatever. Then might represent density of particles, how effective the drug was, how rough the material is, the time stability of the material, or whatever it is. How do you expect a ton of numbers to predict what class it is if you don't even know? So you must know. And since you have 12 zones per image we need to know if the class of each zone is the same (for your ground truth images) or if they can have different classes. You must assign the known, true, ground truth class for each zone and put the data for each zone into the predictor table for your classifier training into one row of the table, as if each zone were its own image. So let's say Class A = "stable over time" and class B = "corrodes rapidly". So for each zone in one image you'd need to know the classes, like maybe they're all A or all B or maybe they go like this [AAABBBAAAABAB]. That's what you have to specify.
Chanille
on 10 Apr 2023
Yes I do know the classes, so here are features for the other classes (Class B and Class C) attached.
The class of each zone is the same. i.e. for class A the zones will have similar classes to eachother but different zone classes to Class B and Class C.
My issue is I don't know how to do this or get it close to working to do that, what about the fitvm draft I sent you? Can it work as a classifier algorthm? but its not working when i run it.
Chanille
on 10 Apr 2023
@Image Analyst for each zone 7 measurements are gathered as ground truth for each class.
Image Analyst
on 11 Apr 2023
Edited: Image Analyst
on 11 Apr 2023
I feel like we're speaking different languages. Your featuresclassA.mat does not have ground truth class assignments in it. It's just a collection of measurements made on each image. Is each filename in that mat file a class? Like file "1_control.tif" is "drug worked perfectly", file "2_control.tif" is class "drug worked slightly", and file "3_control.tif" is "drug did not work at all"? Again measurements are measurements, not ground truth. Do you not have classes defined, and you just have a multidimensional space and you believe you have clusters there, and you want to find out the cluster definitions but you don't know how many clusters you have? There are ways of using kmeans to figure out what the best number of clusters is, in case you don't know for certain.
I don't understand your class definitions. Do you have two classes/types of images:
- one class of images that are "advanced non-restricted class" and
- another set of images that could be called "unknown class 2"?
If so, that's fine but we'll need a bunch of images in each class to train a classifier. You can't do it with just one image of each type. Since 7-dimensional space is impossible to visualize (though we can handle it mathematically), let's use a 2-D analogy. Let's say you had two features: var1 and var2. Now if you plotted those in 2-D you'd have two dots in the x-y graph. And one dot would be class1 and the other dot would be in class 2. But that does not make a good classifier. Let's say you used that model and another image came in with var1 and var 2 being some totally different values than your training set. So now you'd have three dots on your graph. That new, third dot -- which class should it be assigned to? Who can say with just two training points. That's why you need lots of training points.
If you do have two classes like I said above, how do the images of each class look? Is there some obvious noticeable visual difference? If so, show us. There might not be, and that's OK. With 7 features it may be difficult to see a visual difference.
Or, wait for @Walter Roberson
Chanille
on 11 Apr 2023
Edited: Chanille
on 11 Apr 2023
No need to mind read. I just want to make a classier algorithm that can classify images into 3 different classes. I can generate a bunch of image measurements to train the algorithm no problem. But I still don’t know how to create this algorithm before I do that. Do you have an algorithm that classifies that I can upload my data into for training?
Chanille
on 11 Apr 2023
"Is each filename in that mat file a class?" Yes.
"I don't understand your class definitions. Do you have two classes/types of images:
- one class of images that are "advanced non-restricted class" and
- another set of images that could be called "unknown class 2"?" I hve 3 classes/ class A, class B, and class C.
"If so, that's fine but we'll need a bunch of images in each class to train a classifier" Okay. Once i have a bunch of iamges what code can i use to train the classifer?
Image Analyst
on 11 Apr 2023
You can do this:
s = load('featuresclassA.mat')
features = s.features
t = struct2table(features)
% We only have one training set of measurements for each class unfortunately,
% at least in this sample data set. Now we need a vector that is the "true" response
% so we can pass it into Classification Learner.
% Get a list of predictors, which is only the numerical columns.
tPredictors = t(:, 2:end);
% Get a list of true responses.
trueResponses = 1 : height(t);
uiwait(helpdlg('Now you are ready to run Classification Learner'))
classificationLearner(tPredictors, trueResponses);
However your sample data set is not good. You really need to have several rows in the table for each class. Like I tried to explain with the 2-D example if you just have one example of each class, the training is really pretty much meaningless.
Image Analyst
on 11 Apr 2023
Edited: Image Analyst
on 11 Apr 2023
OK, you have measurements from 6 images now, but how many classes do you have? Two? Three? For each of the 6 images, what class are they in? Even one feature is enough. 7 is plenty. But we just need to know what is the "true" class for each of the images? The features are representative of a class but they are not the class number itself.
For example let's say you had 1 feature - the average gray level of the whole image. And let's say you had two classes: "bright images" and "dark images". Now you might have a set of 100 images with all their average brightnesses, but that does not say what class they are in. Perhaps your definition of dark images is where the mean gray level is less than 100. So knowing that you can figure out what class it is. With 7 features, you don't know how to classify them -- if you did you wouldn't need to train a classifier so you must have some other trusted way of saying what class each image is. Perhaps it's just your visual judgment, but whatever it it, you need to have the classes as the "true response" to use in @doc:classificationLearner
Chanille
on 11 Apr 2023
So from what I saw from your code, I import as much features as possible for a SINGLE class into s.
Then when I am redirected to the classifier learner I press train? Or... where am I getting this true vector to pass into the classification learner?
Chanille
on 11 Apr 2023
Edited: Chanille
on 11 Apr 2023
@Image Analyst I know which images they are because the images are already preclassified, so I can say with fact that these features exported to an excel mat belong to a single class (Class A) and Class B respectively. There are only three classes and these measurements are the true class for each image. (i haven't measured the third class yet but I can use the first two classes as a start to building the classifier).
Chanille
on 11 Apr 2023
@Image Analyst I found the true responses. When I select the true responses it says unable to find suitable response variable in the workspace. Not sure why it says that though.
Image Analyst
on 11 Apr 2023
Edited: Image Analyst
on 11 Apr 2023
@Chanille the workbook has three sheets for class A, B, and C. I assume each row contains the measurements from a different file but I'm not sure. What do rows represent? Also there seem to be 10 or 11 feature measurements in each row but I don't know what they are or how they relate to the 7 features (for each zone) that you had before. We can work with that data and just assume that there are 10 features. Here is the code:
% Read in table ta from sheet 'ClassA'.
ta = readtable('CLASSES.xlsx', 'Sheet', 'ClassA');
% Take just Columns 3 to the end
ta = ta(:, 3:end);
% Read in table tb from sheet 'ClassB'.
tb = readtable('CLASSES.xlsx', 'Sheet', 'ClassB');
% Take just Columns 3 to the end
tb = tb(:, 3:end);
% Combine the tables
tPredictors = [ta; tb];
% Create a vector that has the true classes. Class 1 for the top rows (A) and 2 for the lower rows (B)
trueClasses = [ones(height(ta), 1); 2 * ones(height(tb), 1)]
% Setup a session
classificationLearner(tPredictors, trueClasses)
and after running Classification Learner with all models you can see the KNN model is the best:
and the SVM is second best:
I had to delete the extra column you put into the ClassA tab to make sure they had the same variable names and number of columns. That new workbook is attached. If you had 3 classes, you'd just extend the concept in the obvious way.
Chanille
on 11 Apr 2023
@Image Analyst The rows still correspond to previous 7 features and I used the count and area to find the density, normalized the area of the bins and found avgferet/minferet calculations to get additional features for accuracy.
Each row corresponds to 12 different zones per image measured. Thank you @Image Analyst this makes much more sense to me now. I am trying to run the classifier like you did previously on my own attempts I didn't get these results so I am keen to see if i can replicate your set.
Chanille
on 11 Apr 2023
I especially like the your code is not that long, I am not even sure the code I made would work as well yours:
% Load the image data and labels
load('image_data.mat');
load('labels.mat');
% Extract HOG features from the image data
cell_size = 8;
hog_features = extractHOGFeatures(image_data, 'CellSize', [cell_size cell_size]);
% Select the top 50 principal components
num_components = 50;
[coeff, score, latent] = pca(hog_features);
selected_features = score(:, 1:num_components);
% Split the selected features into training and testing sets
[train_data,test_data,train_labels,test_labels] = ...
crossvalind('HoldOut', labels, 0.3);
train_features = selected_features(train_data, :);
test_features = selected_features(test_data, :);
% Train the K-means classifier
num_clusters = 10; % Number of clusters
kmeans_classifier = fitckmeans(train_features, num_clusters);
% Predict the labels for the testing set using the K-means classifier
predicted_labels = predict(kmeans_classifier, test_features);
% Calculate the accuracy of the classifier
accuracy = sum(predicted_labels == test_labels) / numel(test_labels);
% Display the accuracy of the classifier
disp(['The accuracy of the classifier is: ', num2str(accuracy)]);
% Extract HOG features from the new image
new_image = imread('new_image.jpg');
new_hog_features = extractHOGFeatures(new_image, 'CellSize', [cell_size cell_size]);
% Project the new features onto the selected principal components
new_selected_features = (new_hog_features * coeff(:, 1:num_components));
% Predict the class of the new image using the trained K-means classifier
new_label = predict(kmeans_classifier, new_selected_features);
% Display the predicted label of the new image
disp(['The predicted label of the new image is: ', num2str(new_label)]);
Chanille
on 12 Apr 2023
@Image Analyst why is that when i run the classifier I get a different higher accuracy trained model each time:
Image Analyst
on 12 Apr 2023
There is randomness in which rows of data it holds out for validation so it's possible that it could vary slightly each time.
Chanille
on 12 Apr 2023
Edited: Chanille
on 12 Apr 2023
@Image Analyst After I generated the function from the most accurate model, I tried to use new data that i know belongs to either Class A or Class B to see if the classifer would classify the new data corectly.
I uploaded the table with this code on a new compiler tab:
T2 = readtable('T2.xlsx', 'Sheet', 'Sheet1');
yfit = trainedClassifier.predictFcn(T2);
%%Generated fucntion
function [trainedClassifier, validationAccuracy] = trainClassifier(trainingData, responseData)
% [trainedClassifier, validationAccuracy] = trainClassifier(trainingData,
% responseData)
% Returns a trained classifier and its accuracy. This code recreates the
% classification model trained in Classification Learner app. Use the
% generated code to automate training the same model with new data, or to
% learn how to programmatically train models.
%
% Input:
% trainingData: A table containing the same predictor columns as those
% imported into the app.
%
% responseData: A vector with the same data type as the vector
% imported into the app. The length of responseData and the number of
% rows of trainingData must be equal.
%
% Output:
% trainedClassifier: A struct containing the trained classifier. The
% struct contains various fields with information about the trained
% classifier.
%
% trainedClassifier.predictFcn: A function to make predictions on new
% data.
%
% validationAccuracy: A double containing the accuracy as a
% percentage. In the app, the Models pane displays this overall
% accuracy score for each model.
%
% Use the code to train the model with new data. To retrain your
% classifier, call the function from the command line with your original
% data or new data as the input arguments trainingData and responseData.
%
% For example, to retrain a classifier trained with the original data set T
% and response Y, enter:
% [trainedClassifier, validationAccuracy] = trainClassifier(T, Y)
%
% To make predictions with the returned 'trainedClassifier' on new data T2,
% use
% yfit = trainedClassifier.predictFcn(T2)
%
% T2 must be a table containing at least the same predictor columns as used
% during training. For details, enter:
% trainedClassifier.HowToPredict
% Auto-generated by MATLAB on 12-Apr-2023 08:32:47
% Extract predictors and response
% This code processes the data into the right shape for training the
% model.
inputTable = trainingData;
predictorNames = {'Var3', 'Var4', 'Var5', 'Var6', 'Var7', 'Var8', 'Var9', 'Var10', 'Var11', 'Var12'};
predictors = inputTable(:, predictorNames);
response = responseData;
isCategoricalPredictor = [false, false, false, false, false, false, false, false, false, false];
% Train a classifier
% This code specifies all the classifier options and trains the classifier.
classificationNeuralNetwork = fitcnet(...
predictors, ...
response, ...
'LayerSizes', 100, ...
'Activations', 'relu', ...
'Lambda', 0, ...
'IterationLimit', 1000, ...
'Standardize', true, ...
'ClassNames', [1; 2]);
% Create the result struct with predict function
predictorExtractionFcn = @(t) t(:, predictorNames);
neuralNetworkPredictFcn = @(x) predict(classificationNeuralNetwork, x);
trainedClassifier.predictFcn = @(x) neuralNetworkPredictFcn(predictorExtractionFcn(x));
% Add additional fields to the result struct
trainedClassifier.RequiredVariables = {'Var10', 'Var11', 'Var12', 'Var3', 'Var4', 'Var5', 'Var6', 'Var7', 'Var8', 'Var9'};
trainedClassifier.ClassificationNeuralNetwork = classificationNeuralNetwork;
trainedClassifier.About = 'This struct is a trained model exported from Classification Learner R2022a.';
trainedClassifier.HowToPredict = sprintf('To make predictions on a new table, T, use: \n yfit = c.predictFcn(T) \nreplacing ''c'' with the name of the variable that is this struct, e.g. ''trainedModel''. \n \nThe table, T, must contain the variables returned by: \n c.RequiredVariables \nVariable formats (e.g. matrix/vector, datatype) must match the original training data. \nAdditional variables are ignored. \n \nFor more information, see <a href="matlab:helpview(fullfile(docroot, ''stats'', ''stats.map''), ''appclassification_exportmodeltoworkspace'')">How to predict using an exported model</a>.');
% Extract predictors and response
% This code processes the data into the right shape for training the
% model.
inputTable = trainingData;
predictorNames = {'Var3', 'Var4', 'Var5', 'Var6', 'Var7', 'Var8', 'Var9', 'Var10', 'Var11', 'Var12'};
predictors = inputTable(:, predictorNames);
response = responseData;
isCategoricalPredictor = [false, false, false, false, false, false, false, false, false, false];
% Perform cross-validation
partitionedModel = crossval(trainedClassifier.ClassificationNeuralNetwork, 'KFold', 5);
% Compute validation predictions
[validationPredictions, validationScores] = kfoldPredict(partitionedModel);
% Compute validation accuracy
validationAccuracy = 1 - kfoldLoss(partitionedModel, 'LossFun', 'ClassifError');
Chanille
on 12 Apr 2023
Edited: Chanille
on 12 Apr 2023
@Image Analyst But when i ran the classifier, I hit a wall. I imported a new excel sheet in the same format as the one i used to train the model. instead of ClassA or B. I wrote Sheet1 and instead of Class A or B in the row I put ClassX. It gave me the following error:
Unable to resolve the name 'trainedClassifier.predictFcn'.
Error in predictor (line 2)
yfit = trainedClassifier.predictFcn(T2);
%%How can I make the generated function classify new data as being in Class A or Class B?
Image Analyst
on 12 Apr 2023
You need to actually CALL that function so that you have the variable in the workspace. But I don't do that and would not recommend it. I just export the trained model, from the ClassificationLearner Export button, into a variable, then call save() (in the command window) to save that model variable into a .mat file, then load the mat file and call predict. No sense in training the model every time you want to use it to predict new data.
Image Analyst
on 12 Apr 2023
When you load it back in you need to accept it into a variable, like
s = load('trainedModel2.mat')
trainedModel = s.trainedModel2
predictedClasses = predict(trainedModel, yourDataToBeEstimated);
Chanille
on 12 Apr 2023
@Image Analyst Can the yourDataToBeEstimated be T2 where T2 is the excel file I attached earlier?
Chanille
on 12 Apr 2023
s = load('trainedModel2.mat');
trainedModel = s.trainedModel2;
td = readtable('T2.xlsx', 'Sheet', 'Sheet1');
% Take just Columns 3 to the end
td = td(:, 3:end);
predictedClasses = predict(trainedModel, td);
Chanille
on 13 Apr 2023
Hi ImageAnalyst I’m sorry to bother you but it’s my last question, the code I provided above is not working to predict the class for some reason. Thanks and I hope to contribute to this forum some day!
Image Analyst
on 14 Apr 2023
You forgot to upload 'trainedModel2.mat' and 'T2.xlsx', so I can't check anything.
Chanille
on 14 Apr 2023
Edited: Chanille
on 14 Apr 2023
T2 is the new data to be trained.
TrainedModel2 was the exported model from the classifier learner. For some reason when i try to upload it, it only uploads T2 again. But TrainedModel2 is just the exported model after training it and getting the highest accuracy model to test it against.
Chanille
on 14 Apr 2023
Image Analyst
on 14 Apr 2023
In the table there is a class column but there are no classes in it. How am I supposed to know what the true class is for each row?
Also, you might want to put a header line in your workbook so we know what each "Var" really is (like area, mean intensity, or whatever).
If you've already posted it somewhere, then post all files needed in a single reply -- all mat files, all m files, and all xlsx files. The thread is probably the longest I've ever been on and I don't want to have to hunt all around for the needed files.
Chanille
on 14 Apr 2023
Edited: Chanille
on 14 Apr 2023
So to wrap this thread up, I am trying to see if the trained model will correctly classify the T2 table attached to the correct Class, so the T2 shouldn’t have any class information in it so that the trainedmodel2 can do all the classification (?). I will reattach the excel info or do you want me to re-ask the question to decrease the thread? So my last question is coming from me trying to use the exported model to classify other data to the two pretrained classes. But with the 3 lines provided I wasn’t able to classify new data.
Image Analyst
on 14 Apr 2023
I want to do my own training. So, can you give me
- The table of predictor measurements (training set)
- The vector of "true" class numbers for those measurements in the training set
- The table of "test" measurements (that we will use to predict)
- The vector of "true" classes for the training set so we can see how well the predicted class matches up with the "true/known" class values.
I'm pretty sure you can test your test values (those not involved in making the model) right there in the Classification Learner. The "hold outs" used in training (like 20% of your training values) are included in your training data and are called "validation data" and the data not used in training or validating your model are called "test data". So you have 3 data sets involved, or actually 2. There is your "predictor" data from which it automatically splits into "training" and "validation" sets, and then there is your "test" set (which has never been seen during training and model building).
I hope this explains the terminology better.
Chanille
on 15 Apr 2023
Edited: Chanille
on 15 Apr 2023
Here is the training set with variables labeled.
And here is the code to run the trainingset into the classifier:
% Read in table ta from sheet 'ClassA'.
ta = readtable('CLASSES.xlsx', 'Sheet', 'ClassA');
% Take just Columns 3 to the end
ta = ta(:, 3:end);
% Read in table tb from sheet 'ClassB'.
tb = readtable('CLASSES.xlsx', 'Sheet', 'ClassB');
% Take just Columns 3 to the end
tb = tb(:, 3:end);
% Combine the tables
tPredictors = [ta; tb];
% Create a vector that has the true classes. Class 1 for the top rows (A) and 2 for the lower rows (B)
trueClasses = [ones(height(ta), 1); 2 * ones(height(tb), 1)]
% Setup a session
classificationLearner(tPredictors, trueClasses)
Chanille
on 15 Apr 2023
% Create a column vector of zeros to represent observations not belonging to any class
Y = zeros(n, 1);
% Identify observations belonging to Class A
class_A_idx = (X(:, 'Class') == 'Cnt');
% Assign class label 1 to observations belonging to Class A
Y(class_A_idx) = 1;
% Identify observations belonging to Class B
class_B_idx = (X(:, 'Class') == 'WD');
% Assign class label 2 to observations belonging to Class B
Y(class_B_idx) = 2;
% Identify observations belonging to Class C
class_C_idx = (X(:, 'Class') == 'EF');
% Assign class label 3 to observations belonging to Class C
Y(class_C_idx) = 3;
Assuming we have a table of predictor measurements called X with n observations, a corresponding vector of true class labels called Y:
Class A = Cnt, Class B = WD, and Class C = EF otherwise features do not belong to either class
Chanille
on 15 Apr 2023
@Image Analyst In the training set, in each tab there is a column that says Class A, B or C. Each tab corresponds to that class in the column and is thus the true class set that can be used to train and then compare to other values used for the prediction function. In the test set, Class X, Class Y and Class Z belong to Class A, Class B and Class C respectively. (I already know they do because i ran the image analysis program and got those values but i want the code that will classify these values to their classes independently).
i hope I understand your numberings correctly and explained clearly.
Chanille
on 15 Apr 2023
@Image Analyst Thanks for the clarification I understand the terminology very well now.
Chanille
on 17 Apr 2023
@Image Analyst I'll start a new thread for this last question. Scrolling is very long here!
More Answers (0)
See Also
Tags
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!An Error Occurred
Unable to complete the action because of changes made to the page. Reload the page to see its updated state.
Select a Web Site
Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .
You can also select a web site from the following list
How to Get Best Site Performance
Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.
Americas
- América Latina (Español)
- Canada (English)
- United States (English)
Europe
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom(English)
Asia Pacific
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)