%% TEST 1: MLP Z PODZIAŁEM NA ZBIORY (TRAIN, VALIDATION, TEST) % W tym skrypcie trenujemy sieć neuronową typu MLP (Multi-Layer Perceptron) % na zbiorze danych IRIS. Sieć będzie dokonywać klasyfikacji odmian irysów % (Setosa, Versicolor, Virginica). Dodatkowo wykorzystujemy walidację. % potrzebne toolboxy: Deep Learning Toolbox, Statistics and Machine Learning Toolbox, Parallel % Computing Toolbox (dla uczenia z GPU) %% 1. Przygotowanie danych rng('default'); % Ustawiamy generator liczb losowych (dla powtarzalności wyników) load fisheriris % jest w Statistics and Machine Learning Toolbox % Plik 'fisheriris.mat' ładuje do workspace: % - meas: [150x4] -> macierz cech (SepalLength, SepalWidth, PetalLength, PetalWidth) % - species: [150x1] -> nazwy odmian (Setosa, Versicolor, Virginica) X = meas; % Zmienna X (cechy) -> [150x4] Y = categorical(species); % Zmienna Y (etykiety) -> [150x1] (3 kategorie) n = size(X,1); % Liczba próbek = 150 idx = randperm(n); % Losowo permutujemy indeksy 1..150 % Ustalamy proporcje zbiorów: 60% (train), 20% (val), 20% (test) trainRatio = 0.6; valRatio = 0.2; testRatio = 0.2; % Suma = 1.0 nTrain = round(trainRatio * n); % Liczba próbek w zbiorze treningowym nVal = round(valRatio * n); % Liczba próbek w zbiorze walidacyjnym % Pozostałe ~ 20% pójdzie do testu % Wyznaczamy indeksy do train, val, test z losowej permutacji 'idx' trainIdx = idx(1 : nTrain); valIdx = idx(nTrain+1 : nTrain + nVal); testIdx = idx(nTrain + nVal + 1 : end); % Przygotowujemy zbiory XTrain, YTrain, XVal, YVal, XTest, YTest XTrain = X(trainIdx, :); YTrain = Y(trainIdx, :); XVal = X(valIdx, :); YVal = Y(valIdx, :); XTest = X(testIdx, :); YTest = Y(testIdx, :); %% 2. Definicja architektury sieci MLP % MLP = Multi-Layer Perceptron. Zrobimy prostą sieć: % -> Wejście: 4 cechy % -> fullyConnectedLayer(10) + reluLayer % -> fullyConnectedLayer(3) + softmaxLayer + classificationLayer inputSize = 4; % Liczba cech (4: SepalLength, SepalWidth, PetalLength, PetalWidth) numClasses = 3; % Liczba klas (3 odmiany irysa) layers = [ featureInputLayer(inputSize,'Name','input') % warstwa wejściowa fullyConnectedLayer(10,'Name','fc1') % warstwa w pełni połączona (10 neuronów) reluLayer('Name','relu1') % funkcja aktywacji ReLU fullyConnectedLayer(numClasses,'Name','fc2') % warstwa w pełni połączona (3 neurony - 3 klasy) softmaxLayer('Name','softmax') % warstwa softmax (rozkład prawd. dla 3 klas) classificationLayer('Name','classOutput') % warstwa klasyfikująca (entropia krzyżowa) ]; %% 3. Ustawienie opcji treningu z walidacją % Ustawiamy parametry trenowania (opt. 'adam', 50 epok, walidacja itd.) options = trainingOptions('adam', ... 'MaxEpochs', 50, ... 'MiniBatchSize', 16, ... 'ExecutionEnvironment','gpu', ... 'InitialLearnRate', 0.01, ... 'ValidationData', {XVal, YVal}, ... % Zbiór walidacyjny 'ValidationFrequency', 5, ... % Co ile batchy liczymy walidację 'Plots','training-progress', ... 'Verbose',false); %% 4. Trenowanie sieci % trainNetwork trenuje sieć wg. definicji 'layers' i opcji 'options' net = trainNetwork(XTrain, YTrain, layers, options); %% 5. Ocena na zbiorze testowym % Predykcja etykiet na XTest YPred = classify(net, XTest); % Dokładność klasyfikacji accuracy = mean(YPred == YTest); disp("Dokładność (accuracy) na zbiorze testowym: " + accuracy); % Rysujemy macierz pomyłek (confusion matrix) figure; plotconfusion(YTest, YPred); title('Macierz pomyłek: Sieć MLP (IRIS) - Zbiór Testowy'); %% (Opcjonalnie) 6. Tabela z porównaniem wyjść % Tworzymy tabelę (cechy + etykieta rzeczywista + etykieta przewidywana) comparisonTable = array2table(XTest, ... 'VariableNames', {'SepalLength','SepalWidth','PetalLength','PetalWidth'}); comparisonTable.RealLabel = cellstr(YTest); comparisonTable.PredictedLabel = cellstr(YPred); disp("TABELA: Porównanie etykiet rzeczywistych i przewidywanych (zbiór testowy)"); disp(comparisonTable); %% (Opcjonalnie) 7. Wykres 3D punktów (cechy 1,2,3) – dane uczące vs dane testowe figure; hold on; title('Wykres 3D IRIS: Zbiór Treningowy (rzeczywiste etykiety) vs Zbiór Testowy (przewidywane)'); % --- 1. Dane treningowe (rzeczywiste etykiety) --- % Indeksy zbioru treningowego: % trainIdx -> zdefiniowany wcześniej w programie % Wyciągamy z X i Y (a) tylko te próbki i (b) dzielimy na klasy według etykiet rzeczywistych. % Rzeczywiste etykiety w zbiorze treningowym YTrainSetosa = (YTrain == "setosa"); YTrainVersicolor = (YTrain == "versicolor"); YTrainVirginica = (YTrain == "virginica"); % Rysujemy w 3D dane treningowe, kolorem/markerem odzwierciedlając klasy scatter3(XTrain(YTrainSetosa,1), XTrain(YTrainSetosa,2), XTrain(YTrainSetosa,3), ... 'o', 'MarkerEdgeColor','b', 'DisplayName','Trening: setosa'); scatter3(XTrain(YTrainVersicolor,1),XTrain(YTrainVersicolor,2),XTrain(YTrainVersicolor,3),... 'o', 'MarkerEdgeColor','g', 'DisplayName','Trening: versicolor'); scatter3(XTrain(YTrainVirginica,1), XTrain(YTrainVirginica,2), XTrain(YTrainVirginica,3), ... 'o', 'MarkerEdgeColor','r', 'DisplayName','Trening: virginica'); % --- 2. Dane testowe (przewidywane etykiety) --- % Indeksy zbioru testowego: testIdx -> zdefiniowany wcześniej % (Załóżmy, że mamy już YPred = classify(net, XTest).) idxSetosaTest = (YPred == 'setosa'); idxVersicolorTest = (YPred == 'versicolor'); idxVirginicaTest = (YPred == 'virginica'); % Rysujemy w 3D dane testowe, innym markerem (np. kwadrat/kwadrat/diament), % i kolorem dopasowanym do przewidywanej klasy. scatter3(XTest(idxSetosaTest,1), XTest(idxSetosaTest,2), XTest(idxSetosaTest,3), ... 's', 'MarkerEdgeColor','b', 'MarkerFaceColor','b', 'DisplayName','Test pred: setosa'); scatter3(XTest(idxVersicolorTest,1), XTest(idxVersicolorTest,2), XTest(idxVersicolorTest,3), ... 's', 'MarkerEdgeColor','g', 'MarkerFaceColor','g', 'DisplayName','Test pred: versicolor'); scatter3(XTest(idxVirginicaTest,1), XTest(idxVirginicaTest,2), XTest(idxVirginicaTest,3), ... 's', 'MarkerEdgeColor','r', 'MarkerFaceColor','r', 'DisplayName','Test pred: virginica'); % --- 3. Ustawienia wykresu --- grid on; xlabel('Cecha 1: SepalLength'); ylabel('Cecha 2: SepalWidth'); zlabel('Cecha 3: PetalLength'); legend('Location','best');