6. TensorFlow [Электронный ресурс] URL: https://www.tensorflow.org (дата обращения: 10.05.2023).
7. Machine Learning Tutorials - Learn Machine Learning and Artificial Intelligence [Электронный ресурс] URL: https://studymachinelearning.com (дата обращения: 10.05.2023).
8. Гафаров Ф.М. Искусственные нейронные сети и приложения: учеб. пособие / Ф.М. Гафаров, А.Ф. Га-лимянов. Казань: Изд-во Казан. ун-та, 2018. 121 с.
9. Ростовцев В.С. Искусственные нейронные сети: учебник. Санкт-Петербург: Лань, 2019. 213 с.
Исаченков Александр Сергеевич, бакалавр, оператор, era [email protected], Россия, Анапа, ФГАУ «ВИТ «ЭРА»,
Дмитриенко Даниил Богданович, специалист, старший оператор, Россия, Анапа, ФГАУ «ВИТ «ЭРА»,
Фролов Никита Владимирович, бакалавр, старший оператор, Россия, Анапа, ФГАУ «ВИТ «ЭРА»
DATASET PREPARATION AND DATA AUGMENTATION FOR SOLVING THE PROBLEM OF MULTICLASS IMAGE
CLASSIFICATION
A.S. Isachenkov, D.B. Dmitrienko, N. V. Frolov
This article considers the problem of data preparation and augmentation for solving the problem of multiclass image classification using an artificial deep convolutional neural network (CNN). Training and test data sets were formed containing 60 and 25 images, respectively, divided into 6 classes. Image augmentation was performed to create additional data from the existing ones. As a result, approximately 320 images were generated for each class. There are 1887 images in total.
Key words: Dataset, image classification, data augmentation, Keras, deep learning, neural network, CNN.
Isachenkov Aleksandr Sergeevich, bachelor, operator, [email protected]. Russia, Anapa, FGAU «MIT «ERA»,
Dmitrienko Daniil Bogdanovich, specialist, operator, Russia, Anapa, FGAU «MIT «ERA»,
Frolov Nikita Vladimirovich, bachelor, operator, Russia, Anapa, FGAU «MIT «ERA»
УДК 004.512.3
DOI: 10.24412/2071-6168-2023-9-244-245
РАЗРАБОТКА МОБИЛЬНОГО ПРИЛОЖЕНИЯ, ПРЕДОСТАВЛЯЮЩЕГО ПОЛЬЗОВАТЕЛЬСКИЙ ИНТЕРФЕЙС ДЛЯ ИСПОЛЬЗОВАНИЯ НЕЙРОННОЙ СЕТИ, РАЗРАБОТАННОЙ С ИСПОЛЬЗОВАНИЕМ
ФРЕЙМВОРКА KERAS
А.С. Исаченков, Г.П. Эльсессер, О.В. Гречкина
В данной рассматривается задача конвертации нейронной сети, разработанной с использованием библиотеки Keras в формат Tensorflow Lite, её перенос на мобильное устройство под управлением Android, и использование нейронной сети в приложении. Было разработано мобильное приложения для Android, которое позволяет загружать изображения из файловой системы устройства, передавать их на обработку нейронной сети, получать и выводить результат классификации на экран.
Ключевые слова: Android, Tensorflow Lite, Keras, нейронная сеть.
После разработки нейронной сети, которая решает определённую задачу, возникает необходимость превратить её в удобный инструмент. То есть нейронную сеть нужно упаковать в удобное и простое в использовании пользовательское приложение.
В данной работе рассматривается, как конвертировать нейронную сеть с помощью tensoflow-lite, перенести её на мобильное устройство под управлением Android, и использовать нейросеть в приложении.
Цель работы: разработка мобильного приложения, предоставляющего пользовательский интерфейс для использования нейронной сети.
Для достижения поставленной цели необходимо решить следующие задачи:
1) определить существующие способы интеграции нейронной сети в мобильное приложение;
2) внедрить нейросеть в Android приложение, используя наиболее подходящий метод;
3) разработать интерфейс Android приложения;
4) реализовать логику взаимодействия Android приложения с нейронной сетью.
Для разработки приложения использовались IDE Android Studio и язык программирования Java, а также нейронная сеть, написанная на языке программирования Python с использованием фреймворка глубокого обучения Keras.
Подготовка обученной модели к внедрению в Android приложение.
Способы интеграции нейронной сети в приложение. Возможности интеграции Android приложения и нейронной сети довольно широкие. На рис. 1 приведена диаграмма, на которой приведены способы интеграции нейронной сети в приложение [1].
Рис 1. Способы интеграции нейронной cerní е приложение
Как видим, есть два основных пути интеграции:
1. Сеть внутри приложения
2.Сеть на сервере
Сильными и очень привлекательными сторонами при размещении сети внутри приложения являются:
• бесплатность;
• скорость отклика (нет запроса по сети);
• возможность работать там, где сети нет.
Ограничением же для размещения сети внутри приложения является память. При чём как оперативная память целевого устройства, так и размер приложения.
Самой главной сильной стороной расположения сети на сервере является преодоление ограничения, связанного с памятью и размерами приложения клиентской части. Сейчас для развертывания серьёзной сети альтернативы просто нет. [1]
Конвертация нейронной сети Keras в формат Tensorflow Lite. Для целей переноса модели на мобильное устройство был использован tensorflow-lite. Сам по себе tensorflow-lite представляет из себя набор утилит, преследующий две основные цели.
1.Сделать из нейросети модель, приемлемую для мобильного устройства. Обычно под этим подразумевается уменьшение размера и сложности сети, что, в свою очередь, приводит к небольшому падению точности работы. Тем не менее, это необходимый компромисс между аккуратностью работы нейросети и ее размерами на мобильном устройстве.
2.Создание среды выполнения для различных мобильных платформ, включая Android, ios, микроконтроллеры. [2]
Необходимо выполнить следующую команду в папке с сохранённой моделью: tflite_convert --output_file="mushrooms-model.tflite" --keras_model_file="mushrooms-model.h5"
Для удобства запуска скрипта в случае изменения модели, код команды был сохранён в файл "convert_tflite.bat" в папке с моделью.
После выполнения скрипта в папку с моделью будет помещён файл "mushrooms-model.tflite" в формате tensorflow-lite.
Готовую .tflite-модель можно использовать в различных окружениях, например Android или ios. Разработка Android приложения. Внедрение нейронной сети в Android приложение. После создания модели нейросети и ее конвертации в формат tensorflow-lite, необходимо создать приложение для Android. Для этой цели испольуется IDE - Android Studio и язык программирования Java.
Для подключения билиотеки Tensorflow lite необходимо добавить следующие зависимости в файл "build.gradle":
implementation ' org.tensorflow:tensorflow-lite:2.9.0' В этом же файле необходимо добавить: aaptOptions {
noCompress "tflite" noCompress "lite"
}
Теперь нужно добавить в проект саму модель нейросети tf-lite. Для этого в папке "main" следует создать папку "assets" и перенести туда ранее конвертированную модель. [2]
Для того чтобы использовать нейронную сеть, необходимо предоставить приложению данные о:
1) количестве распознаваемых классов,
2) размере входного изображения.
А также о том, каким позициям в возвращаемом нейросетью векторе, какие соответствуют названия классов.
Эти данные можно указать напрямую в коде приложения, но с точки зрения архитектуры более гибким решением будет хранить данные параметры в конфигурационных файлах.
Для этого в обучающий скрипт необходимо добавить запись данных параметров в файл. Запись информации о классах:
class_map = {v: k for k, v in train_generator.class_indices.items()}
classes_str = ""
for key, value in class_map.items():
classes_str += str(key) + ': ' + value + "\n" file = open('classes.txt', 'w') file.write(classes_str) Запись информации о параметрах: file = open('params.cfg', 'w') params = \
'INPUT_WIDTH: ' + str(IMG_SIZE) + '\n' + \ 'INPUT_HEIGHT: ' + str(IMG_SIZE) + V + \ 'CLASSES_COUNT: ' + str(train_generator.num_classes) + '\n' file.write(params)
В результате будет сгенерировано два файла со следующим содержанием:
Файл classes.txt:
0: Borovik
1: Dojdevik
2: Lisichka
3: Muhomor
4: Podberezovik
5: Volnushka
Файл params.cfg:
INPUT_WIDTH: 48
INPUT_HEIGHT: 48
CLASSES_COUNT: 6
Использование нейронной сети в Android приложении. MainActivity. В первую очередь был разработан интерфейс приложения (рис. 2). Для первого прототипа предполагается загрузка изображения из галереи.
РАСПОЗНАТЬ
Рис. 2. Макет графического интерфейса
Далее необходимо реализовать функциональность метода classify, которое будет выполняться при нажатии на кнопку «Распознать».
public void onClassify(View view) {
String className = classifier.classify(currentlmage); textView.setText('^ думаю, что это " + className);
}
Так же в классе MainActivity реализована функциональность по загрузке изображения из галереи и отображению его на экране. В итоге код класса имеет следующий вид: public class MainActivity extends AppCompatActivity {
private ImageView imageView; private Bitmap currentImage; private TextView textView;
ActivityResultLauncher<Intent> activityResultLauncher = registerForActivityResult( new ActivityResultContracts.StartActivityForResult(), result -> {
if (result.getResultCode() == Activity.RESULT_OK) { if (result.getData() != null) { pickImage(result.getData());
}
}
});
private Classifier classifier; @Override
protected void onCreate(Bundle savedlnstanceState) { super.onCreate(savedlnstanceState);
AppCompa®elegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
ClassifierBuilder classifierBuilder = new ClassifierBuilder(this.getAssetsO);
classifier = classifierBuilder.create();
setContentView(R.layout. activity _main);
imageView = (ImageView) findViewByld(R.id.imageView);
textView = (TextView) findViewByld(R.id.textView);
}
public void onLoad(View view) {
Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
photoPickerIntent.setType("image/*");
activityResultLauncher.launch(photoPickerIntent);
}
private void pickImage(Intent imageReturnedIntent) { try {
Uri imageUri = imageReturnedIntent.getData();
InputStream imageStream = getContentResolver().openInputStream(imageUri); currentImage = BitmapFactory.decodeStream(imageStream); imageView.setImageBitmap(currentImage); } catch (FileNotFoundException e) { e.printStackTrace();
}
}
public void onClassify(View view) { if (currentImage == null) { return;
}
if (classifier == null) {
throw new IllegalStateException("classifier has not been initialized");
}
String className = classifier.classify(currentImage); textView.setText('^ думаю, что это " + className);
}
}
Classifier. Необходимо реализовать класс Classifier с методом classify(Bitmap bitmap). public class Classifier {
private final Interpreter interpreter;
private final int INPUT_WIDTH;
private final int INPUT_HEIGHT;
private final int CLASSES_COUNT;
private final Map<Integer, String> classesMap;
Classifier(ByteBuffer modelBuffer, int input_width, int input_height, int classes_count, Map<Integer, String>
classesMap) {
this.INPUT_WIDTH = input_width; this.INPUT_HEIGHT = input_height; this.CLASSES_COUNT = classes_count; this.interpreter = new Interpreter(modelBuffer); this.classesMap = classesMap;
}
private float[][][][] getDataForInput(Bitmap currentImage) {
Bitmap resizedBitmap = Bitmap.createScaledBitmap(currentImage, INPUT_WIDTH, INPUT_HEIGHT,
false);
int[][][] ints = ImageUtils.toPixels(resizedBitmap);
float[] [][][] normalizedData = new float[1][INPUT_WIDTH][INPUT_HEIGHT][3]; for (int i = 0; i < ints.length; i++) { for (int j = 0; j < ints[i].length; j++) { for (int k = 0; k < ints[i][j].length; k++) { normalizedData[0][i][j][k] = ints[i][j][k] / 255.0f;
}
}
}
return normalizedData;
}
public String classify(Bitmap bitmap) {
float[][] output = new float[1][CLASSES_COUNT]; interpreter.run(getDataForInput(bitmap), output); List<Float> outputValues = new ArrayList<>(); for (float v : output[0]) {
outputValues.add(v);
}
Float maxValue = Collections.max(outputValues); int index = outputValues.indexOf(maxValue); return classesMap.get(index);
}
}
Класс Classifier имеет 5 полей: входные ширина и высота изображения, количество классов, отображение позиций вектора вероятностей на названия классов, а также объект Interpreter, который должен быть проинициали-зирован моделью из файла .tflite.
Метод getDataForlnput сжимает изображение BitMap до входного разммера (в данном случае 48*48) и конвертирует его в массив нормализованную матрицу пикселей (т.е. каждый элемент принимает значение от 0 до 1), с первой размерностью 1 (для соответствия форме входного вектора в первом слое нейронной сети). Таким образом, в данном случае размерность вектора будет [1, 48, 48, 3].
Для конвертации BitMap в матрицу пикселей необходимо преобразовать его в массив шестнадцатеричных чисел, соответствующих коду цвета в системе ARGB, затем конвертировать каждое число в массив из 3-х значений для каналов RGB. За эти преобразования отвечают методы toPixels и argbHexTolntTriple из класса ImageUtils. public class ImageUtils { public static int[][][] toPixels(Bitmap bitmap) {
int[] pixels = new int[bitmap.getWidth() * bitmap.getHeight()];
bitmap.getPixels(pixels, 0, bitmap.getWidthO, 0, 0, bitmap.getWidth(), bitmap.getHeightO); List<int[]> collect = Arrays.stream(pixels) .mapToObj(Integer::toHexString) .map(ImageUtils::argbHexToIntTriple) .collect(Collectors.toList()); return splitBy(collect, bitmap.getWidth()).stream() .map(ints -> ints.toArray(new int[0][])) .toArray(int[] [][]::new);
}
private static <T> List<List<T>> splitBy(List<T> list, int len) { List<List<T>> newList = new ArrayList<>(); for (int pos = 0; pos < list.size(); pos += len) { newList.add(list.subList(pos, pos + len));
}
return newList;
}
private static int[] argbHexToIntTriple(String s) {
return Stream.of(s.substring(2, 4), s.substring(4, 6), s.substring(6, 8)) .mapToInt(value -> Integer.parseInt(value, 16)) .toArray();
}
}
Метод classify(Bitmap bitmap) создаёт шаблон для записи массива выходных значений с заданным размером (в данном случае [1,6]) и вызывает метод run у объекта interpreter. Затем находится индекс максимального элемента в выходном векторе и выполняется его преобразование в название класса.
ClassifierBuilder. Так как считывание модели, чтение и инициализация параметров для создания объекта класса Classifier - это достаточно сложный процесс, то для его выполнения бьш создан отдельный класс-билдер -ClassifierBuilder. Класс считывает модель, инициализирует объект класса Interpreter, считывает параметры из файлов params.cfg и classes.txt, инициализирует параметры для создания объекта Classifier и возвращает созданный объект. public class ClassifierBuilder { public static final String MODEL_TFLITE_FILE = "mushrooms-model.tflite"; public static final String PARAMS_FILE = "params.cfg"; public static final String CLASSES_FILE = "classes.txt"; private final AssetManager assetManager; ClassifierBuilder(AssetManager assetManager) { this.assetManager = assetManager;
}
private static String tryGetParam(String name, Map<String, String> params) { String value = params.get(name); if (value == null) {
throw new IllegalArgumentException("Param " + name + " does not found");
}
return value;
}
public Classifier create() {
ByteBuffer model = getModel(); if (model == null) { throw new RuntimeException("Не удалось считать модель");
}
Map<String, String> params = readParamsMap(PARAMS_FILE);
int inputWidth = Integer.parseInt(tryGetParam("INPUT_WIDTH", params));
int inputHeight = Integer.parseInt(tryGetParam("INPUT_HEIGHT", params)); int classesCount = Integer.parseInt(tryGetParam("CLASSES_COUNT", params)); Map<Integer, String> classesMap = readParamsMap(CLASSES_FILE, Integer::parseInt); return new Classifier(model, inputWidth, inputHeight, classesCount, classesMap);
}
private Map<String, String> readParamsMap(String file) { return readParamsMap(file, s -> s);
}
@NonNull
private <K> Map<K, String> readParamsMap(String file, Function<String, K> keyFunction) { return getLines(file)
.map(s -> s.split(": "))
.collect(Collectors.toMap(strings -> keyFunction.apply(strings[0]), strings -> strings[1]));
}
private ByteBuffer getModel() { AssetF ileDescriptor fileDescriptor;
try {
fileDescriptor = assetManager.openFd(MODEL_TFLITE_FILE); } catch (IOException e) { e.printStackTrace(); return null;
}
long startOffset = fileDescriptor.getStartOffset();
long declaredLength = fileDescriptor.getDeclaredLength();
try (FilelnputStream fis = new FileInputStream(fileDescriptor.getFileDescriptor())) {
return fis.getChannel().map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength); } catch (IOException e) { e.printStackTrace(); return null;
}
}
private Stream<String> getLines(String file) { InputStream inputStream; try {
inputStream = assetManager.open(file); } catch (IOException e) { throw new IllegalArgumentException("He удалось прочитать файл " + file);
}
return new BufferedReader(new InputStreamReader(inputStream)).lines();
}
}
Тестирование. На рис. 3 представлены скриншоты результатов работы приложения. Изображение было загружено из галереи и правильно классифицировано нейронной сетью. Заключение. В результате выполнения работы были изучены такие способы интеграции нейронной сети в мобильное приложение, как: встроенная сеть и сеть на сервер - для выполнения работы было решено конвертировать нейронную сеть в модель tensoflow-lite, так как этот способ является бесплатным, а модель нейронной сети используется небольшая.
а б в г
Рис. 3. Результат работы приложения: а - стартовая страница; б - после нажатия на кнопку «Загрузить»; в - загруженное изображение, г - после нажатия на кнопку «Распознать»
Было разработано мобильное приложения для Android, которое позволяет загружать изображения из файловой системы устройства, передавать их на обработку нейронной сети, получать и выводить результат классификации на экран.
Приложение протестировано: изображение загружается из галереи и правильно классифицируется нейронной сетью.
Список литературы
1.Как перенести нейросеть на мобильное устройство [Электронный ресурс] URL: https://habr.com/ru/post/570052 (дата обращения: 10.05.2023).
2.Выводим нейронную сеть в продакшн для Android приложения [Электронный ресурс] URL: https://habr.com/ru/pos1/467055(дата обращения: 10.05.2023).
3.Sangaiah A.K. Deep learning and parallel computing environment for bioengineering systems. Amsterdam: Academic Press, 2019.
4.Шолле Ф. Глубокое обучение на Python. СПб: Питер, 2018. 400 c.
5.Keras [Электронный ресурс] URL: https://ru.wikipedia.org/wiki/Keras (дата обращения: 10.05.2023).
6.Keras: the Python deep learning API [Электронный ресурс] URL: https://keras.io (дата обращения: 10.05.2023).
7.Keras-Слои - Русскоязычная документация Keras [Электронный ресурс] URL: https://ru-keras.com (дата обращения: 10.05.2023).
8.TensorFlow [Электронный ресурс] URL: https://www.tensorflow.org (дата обращения: 10.05.2023).
9.Machine Learning Tutorials - Learn Machine Learning and Artificial Intelligence [Электронный ресурс] URL: https://studymachinelearning.com (дата обращения: 10.05.2023).
10. Гафаров Ф.М. Искусственные нейронные сети и приложения: учеб. пособие / Ф.М. Гафаров, А.Ф. Га-лимянов. Казань: Изд-во Казан. ун-та, 2018. 121 с.
11. Ростовцев В.С. Искусственные нейронные сети: учебник. Санкт-Петербург: Лань, 2019. 213 с.
Исаченков Александр Сергеевич, бакалавр, оператор, [email protected]. Россия, Анапа, ФГАУ «ВИТ «ЭРА»,
Эльсессер Григорий Павлович, магистр, оператор, Россия, Анапа, ФГАУ «ВИТ «ЭРА»,
Гречкина Олексия Валерьевна, младший научный сотрудник, 1 научно-исследовательского отдела (экспертизы информационных проектов и научно-исследовательской деятельности), Россия, Анапа, ФГАУ «ВИТ «ЭРА»
DEVELOPMENT OF A MOBILE APPLICATION PROVIDING A USER INTERFACE TO USE A NEURAL NETWORK
DEVELOPED USING THE KERAS FRAMEWORK
A.S. Isachenkov, G.P. Elsesser, O. V. Grechkina
This article discusses the task of converting a neural network developed using the Keras library to the Tensorflow Lite format, transferring it to an Android mobile device, and using the neural network in an application. A mobile application for Android was developed that allows you to download images from the device's file system, transfer them to the processing of a neural network, receive and display the classification result on the screen.
Key words: Android, Tensorflow Lite, Keras, neural network.
Isachenkov Aleksandr Sergeevich, bachelor, operator, [email protected], Russia, Anapa, FGAU «MIT «ERA»,
Elsesser Grigory Pavlovich, master, operator, Russia, Anapa, FGAU «MIT «ERA»,
Grechkina Oleksia Valerievna, junior researcher, 1st research department, (examination of information projects and research activities), Russia, Anapa, FGAU «MIT «ERA»
УДК 621.31
DOI: 10.24412/2071-6168-2023-9-250-251
СИСТЕМА ЗАЗЕМЛЕНИЯ ЖИЛОГО ДОМА С РАЗДЕЛЕНИЕМ РАБОЧЕГО И ЗАЩИТНОГО ПРОВОДНИКА
П.А. Конов, Н.А. Чушкин, И.А. Тычков
Данная статья обсуждает актуальность требований к безопасному использованию электроприемников, в связи с ростом мощности и разнообразием электротехнического оборудования. В статье приводятся примеры использования таких типов заземлений как защитное и рабочее заземление, а также объясняется разница между заземлением и занулением. Особое внимание статья уделяет модернизации существующих сетей в непроизводственных постройках, построенных до 1998 года, когда использовалась система TN-C с отсутствием отдельного заземляющего проводника. Данная статья также отмечает растущую мощность в бытовых электрических сетях из-за увеличения числа бытовой техники, проблемы с устаревшей проводкой и недостатком финансирования и квалификации персонала. Она подчеркивает важность обновления и модернизации электрической инфраструктуры.
Ключевые слова: система TN-S, система TN-C-S, система TN-C, электробезопасность, электроснабжение, Нормативы Правил устройства электроустановок (ПУЭ), квалификация персонала, заземление, зануление.
В связи с ростом единичной мощности и многообразием электроприемников требования к безопасному использованию становятся все более актуальными. Требования, внедренные в действие нормативными документами в нашей стране, ужесточили правила эксплуатации электротехнического оборудования. После этого действующие с советских времен государственные стандарты с упрощенными правилами заземления электрических схем для жилых домов пересмотрены [1].