Скачиваний:
7
Добавлен:
16.08.2023
Размер:
30.64 Кб
Скачать

Федеральное агентство связи

Федеральное государственное образовательное бюджетное учреждение высшего образования «Санкт-Петербургский государственный университет телекоммуникаций им. проф. М.А.Бонч-Бруевича»

Факультет «Инфокоммуникационных сетей и систем»

Кафедра «Программной инженерии и вычислительной техники»

Отчет

Лабораторная работа №3

Дисциплина: Проектирование и архитектура программных систем

Студент группы

ИКПИ-93

________________

Козлов Н.С

кандидат

технических наук

_________________

Кокарев А.С.

Санкт-Петербург

2023

Оглавление

Постановка задачи

Студент самостоятельно выбирает готовый программный модуль (код) – это может быть любая компьютерная программа или её фрагмент объёмом не менее 100 и не более 500 операторов. Программа может быть сторонняя или разработанная студентами ранее.

В зависимости от субъективной оценки исходного кода, студент выбирает наиболее подходящие метрики для оценки (из представленного списка см. лекции). Количество метрик и их сложность расчёта остаётся в профессиональной компетенции студента и субъективно должны соответствовать достаточной трудоёмкости расчёта для признания преподавателем проработанности теоретической темы студентом. Студент вправе воспользоваться также любыми метриками, которые не вошли в лекционный список. Углублённое изучение выбранных метрик прерогатива студента. Работа, представленная на уровне положительной оценки, автоматически снимает тему метрик с теоретического зачёта.

Программный модуль

Для оценки был выбран модуль программы нейронной сети, написанный на С++. Данный модуль имплементирует структуру нейрона. Код модуля можно найти в листинге 1.

Листинг 1 - Код оцениваемой программы.

С++

// Author: Nikita Kozlov

// Link: github.com/nyarstot

//

// This file is part of WaifuGenerator neural network.

//

// WaifuGenerator is free software: you can redistribute it and/or modify

// it under terms of the GNU Generan Public License as published by

// the free software foundation, either version 3 of License, or

// (at your option) any later version.

//

// WaifuGenerator is distributed in the hope that it will be usefull,

// but WITHOUT ANY WARRANTY; without even the implied warranty of

// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the

// GNU General Public License for more details.

//

// You should have received a copy of the GNU General Public License

// along with WaifuGenerator. If not, see <https://www.gnu.org/licenses/>.

#include "waifupch.h"

#include "Neuron.h"

WaifuCPU::Neuron::Neuron(size_t outputAmount, size_t neuronIndex)

{

for (size_t i{}; i < outputAmount; i++) {

m_OutputWeights.push_back(Connector());

m_OutputWeights.back().m_RedWeight = this->randomizeWeight();

m_OutputWeights.back().m_GreenWeight = this->randomizeWeight();

m_OutputWeights.back().m_BlueWeight = this->randomizeWeight();

}

m_NeuronIndex = neuronIndex;

}

double _WF_CALL Neuron::randomizeWeight()

{

return rand() / double(RAND_MAX);

}

_WF_CALL PixelRGB _WF_CALL Neuron::activationFunction(PixelRGB value)

{

double tanhRed = tanh(value[0]);

double tanhGreen = tanh(value[1]);

double tanhBlue = tanh(value[2]);

return PixelRGB(tanhRed, tanhGreen, tanhBlue);

}

_WF_CALL PixelRGB _WF_CALL Neuron::activationFunctionDerivative(PixelRGB value)

{

double drvtRed = 1 / pow(cosh(value[0]), 2);

double drvtGreen = 1 / pow(cosh(value[1]), 2);

double drvtBlue = 1 / pow(cosh(value[2]), 2);

return PixelRGB(drvtRed, drvtGreen, drvtBlue);

}

_WF_CALL PixelRGB _WF_CALL Neuron::sumDOW(const std::vector<Neuron>& nextLayer)

{

double sumRed = 0.0f;

double sumGreen = 0.0f;

double sumBlue = 0.0f;

if (nextLayer.size() == m_OutputWeights.size()) {

for (size_t i{}; i < nextLayer.size() - 1; i++) {

sumRed += m_OutputWeights[i].m_RedWeight * nextLayer[m_NeuronIndex].m_RedGradient;

sumGreen += m_OutputWeights[i].m_GreenWeight * nextLayer[m_NeuronIndex].m_GreenGradient;

sumBlue += m_OutputWeights[i].m_BlueWeight * nextLayer[m_NeuronIndex].m_BlueGradient;

}

}

if (nextLayer.size() != m_OutputWeights.size()) {

for (size_t i{}; i < m_OutputWeights.size() - 1; i++) {

for (size_t j{}; j < nextLayer.size() - 1; j++) {

sumRed += m_OutputWeights[i].m_RedWeight * nextLayer[j].m_RedGradient;

sumGreen += m_OutputWeights[i].m_RedWeight * nextLayer[j].m_GreenGradient;

sumBlue += m_OutputWeights[i].m_RedWeight * nextLayer[j].m_BlueGradient;

}

}

}

return PixelRGB(sumRed, sumGreen, sumBlue);

}

void _WF_CALL Neuron::feedForward(const std::vector<Neuron>& prevLayer)

{

double sumRed = 0.0f;

double sumGreen = 0.0f;

double sumBlue = 0.0f;

for (size_t i{}; i < prevLayer.size(); i++) {

sumRed = prevLayer[i].getOutputValue()[0] * prevLayer[i].m_OutputWeights[m_NeuronIndex].m_RedWeight;

sumGreen = prevLayer[i].getOutputValue()[1] * prevLayer[i].m_OutputWeights[m_NeuronIndex].m_GreenWeight;

sumBlue = prevLayer[i].getOutputValue()[2] * prevLayer[i].m_OutputWeights[m_NeuronIndex].m_BlueWeight;

}

m_OutputValue = this->activationFunction(PixelRGB(sumRed, sumGreen, sumBlue));

}

void _WF_CALL Neuron::calcOutputGradient(PixelRGB targetValues)

{

double deltaRed = targetValues[0] - m_OutputValue[0];

double deltaGreen = targetValues[1] - m_OutputValue[1];

double deltaBlue = targetValues[2] - m_OutputValue[2];

PixelRGB drvtRGB = this->activationFunctionDerivative(PixelRGB(deltaRed, deltaGreen, deltaBlue));

m_RedGradient = deltaRed * drvtRGB[0];

m_GreenGradient = deltaGreen * drvtRGB[1];

m_BlueGradient = deltaBlue * drvtRGB[2];

}

void _WF_CALL Neuron::calcHiddenGradient(const std::vector<Neuron>& nextLayer)

{

PixelRGB dow = sumDOW(nextLayer);

PixelRGB outDerivative = this->activationFunctionDerivative(m_OutputValue);

m_RedGradient = dow[0] * outDerivative[0];

m_GreenGradient = dow[1] * outDerivative[1];

m_BlueGradient = dow[2] * outDerivative[2];

}

void _WF_CALL Neuron::updateWeights(std::vector<Neuron>& prevLayer)

{

for (size_t i{}; i < prevLayer.size(); ++i) {

Neuron& l_Neuron = prevLayer[i];

double oldDeltaRedWeight = l_Neuron.m_OutputWeights[m_NeuronIndex].m_DeltaRedWeight;

double oldDeltaGreenWeight = l_Neuron.m_OutputWeights[m_NeuronIndex].m_DeltaGreenWeight;

double oldDeltaBlueWeight = l_Neuron.m_OutputWeights[m_NeuronIndex].m_DeltaBlueWeight;

double newDeltaRedWeight = C_ETA * l_Neuron.getOutputValue()[0] * m_RedGradient + C_ALPHA * oldDeltaRedWeight;

double newDeltaGreenWeight = C_ETA * l_Neuron.getOutputValue()[1] * m_GreenGradient + C_ALPHA * oldDeltaGreenWeight;

double newDeltaBlueWeight = C_ETA * l_Neuron.getOutputValue()[2] * m_BlueGradient + C_ALPHA * oldDeltaBlueWeight;

// Set to neuron

l_Neuron.m_OutputWeights[m_NeuronIndex].m_DeltaRedWeight = newDeltaRedWeight;

l_Neuron.m_OutputWeights[m_NeuronIndex].m_RedWeight += newDeltaRedWeight;

l_Neuron.m_OutputWeights[m_NeuronIndex].m_DeltaGreenWeight = newDeltaGreenWeight;

l_Neuron.m_OutputWeights[m_NeuronIndex].m_GreenWeight += newDeltaBlueWeight;

l_Neuron.m_OutputWeights[m_NeuronIndex].m_DeltaBlueWeight = newDeltaBlueWeight;

l_Neuron.m_OutputWeights[m_NeuronIndex].m_BlueWeight += newDeltaBlueWeight;

}

}

В ходе выполнения работы были подсчитано количество уникальных операторов и операндов встречающихся в коде программы. Значения подсчётов представлены в таблицах 1-4.

Таблица 1 – Количество уникальных операторов.

Оператор

Количество использований

.

64

,

14

;

68

:

28

[]

58

{}

23

::

14

->

6

&

5

()

60

!=

1

+=

9

==

1

=

43

+

3

++

6

-

12

<

10

>

10

include

2

double

23

this

6

size_t

8

void

4

Продолжение таблицы 1.

_WF_CALL

11

for

7

return

4

if

2

const

3

pow()

3

cosh()

3

rand()

1

tanh()

3

PixelRGB()

14

randomizeWeight()

4

activationFunction()

2

activationFunctionDerivative()

3

sumDOW()

2

size()

9

feedForward()

1

getOutputValue()

6

calcOutputGradient()

1

calcHiddenGradient()

1

updateWeights()

1

Neuron

16

*

24

Таблица 2 – Общее количество операторов.

Всего операторов

Количество использований

46

599

Таблица 3 – Количество уникальных операндов.

Операнд

Число использований

m_OutputWeights

25

outputAmount

2

neuronIndex

2

m_RedWeight

7

m_GreenWeight

4

m_BlueWeight

4

m_NeuronIndex

16

neuronIndex

2

RAND_MAX

1

value

8

tanhRed

2

tanhGreen

2

tanhBlue

2

drvtRed

2

drvtGreen

2

drvtBlue

2

nextLayer

13

sumRed

7

sumGreen

7

sumBlue

7

targetValues

4

m_OutputValue

5

Таблица 4 – Общее количество операндов.

Всего операндов

Количество использований

22

126