Compare commits

...

27 Commits

Author SHA1 Message Date
Basyrov Rustam
a80e20862c add jenkins to CV 2025-06-02 17:22:05 +03:00
Basyrov Rustam
6bddd048ca remove test stuff 2025-06-02 17:14:34 +03:00
Basyrov Rustam
fd3225b8b3 Test 2025-06-02 17:10:58 +03:00
Basyrov Rustam
eb295fdf41 fix "about me" page 2025-06-02 13:55:09 +03:00
Basyrov Rustam
4ebb210103 fix typo 2025-05-30 16:06:44 +03:00
Basyrov Rustam
3595549e62 add date 2025-05-30 16:03:24 +03:00
Basyrov Rustam
e61c314311 add some references 2025-05-30 16:03:21 +03:00
Basyrov Rustam
304c3cc1d4 remove some stuff 2025-05-30 15:48:31 +03:00
Basyrov Rustam
457a1d397b finish article type-pred 2025-05-30 15:44:35 +03:00
Basyrov Rustam
96910eea02 add signature calculating note 2025-05-30 15:29:09 +03:00
Basyrov Rustam
f180169558 new index to working ToC 2025-05-30 14:04:51 +03:00
Basyrov Rustam
8456b95098 some new settings
going to mkdocs-material
2025-05-30 14:03:11 +03:00
Basyrov Rustam
ac172c0357 add code block descriptions 2025-05-30 13:39:37 +03:00
Basyrov Rustam
d04ae45f10 some addings 2025-05-29 21:04:48 +03:00
Basyrov Rustam
9f012896d8 add link to Gauss's smoothing 2025-05-29 21:04:42 +03:00
Basyrov Rustam
80a547df3b add png's 2025-05-29 21:04:12 +03:00
Basyrov Rustam
8af5a68a39 neural network 2025-05-12 21:01:19 +03:00
Basyrov Rustam
b71d1d4809 new stage 2025-05-11 20:11:03 +03:00
rustam
424e72f232 two heads 2025-05-10 15:54:28 +03:00
Basyrov Rustam
709bb61cf3 Intro 2025-05-09 19:08:31 +03:00
Basyrov Rustam
7d93ef9790 references 2025-05-09 18:48:21 +03:00
Basyrov Rustam
1bfac10d9a pics? 2025-05-09 18:46:24 +03:00
Basyrov Rustam
48d07c7d65 headers 2025-05-06 17:27:21 +03:00
Basyrov Rustam
d21f1db4bf Merge branch 'main' into filetype_prediction 2025-05-05 22:33:27 +03:00
Basyrov Rustam
2ad1e0c48d fix typo in article name 2025-05-05 22:33:20 +03:00
Basyrov Rustam
b5d706683c init new article 2025-05-04 22:07:46 +03:00
Basyrov Rustam
344ee7a343 Merge pull request #4 from rustbas/dev
ACH
2025-04-23 19:13:48 +03:00
10 changed files with 231 additions and 33 deletions

View File

@@ -1,4 +1,4 @@
# Немного о принятии решений и нейросетях
# Немного про принятие решений и нейросети
## Мотивация

View File

@@ -1,3 +1,3 @@
# Общие заметки
## 2025-04-23 [Немного о принятии решений и нейросетях](ach.md)
## 2025-04-23 [Немного про принятие решений и нейросети](ach.md)

View File

@@ -3,15 +3,27 @@
Меня зовут Рустам.
Люблю Linux и все, что связано с ним.
Увлекаюсь автоматизацией, аналитикой и программированием, а также смежными
направлениями.
Предпочитаю командную строку графическим
приложениям.
Ввиду того, что я часто делаю "*Proof of Concept*" и "*Probe*" проекты, было
решено завести для этого блог.
Также увлекаюсь математической статистикой и машинным обучением.
Здесь время от времени выкладываю заметки по различным темам, которые мне
показались интересными.
В свободное время, если есть возможность, занимаюсь спортивным туризмом, в
частности, горным. В 2019 году взошел на Казбек (5033 м, 2Б к.с.) и в 2021 году
— на Эльбрус (5642 м, 2А к.с.).
# Технологический стэк
# TBD
- **Администрирование**: дистрибутивы Linux, права доступа, управление
процессами, **nginx** (веб-сервер), сетевые протоколы, ведение документации
(**mkdocs**);
- **DevOps**: основы **docker** и **ansible**, docker-compose (в т.ч.
Portainer), основы **CI/CD** (GitHub Actions, GitLab CI, Jenkins);
- **Программирование**: **python** (в том числе: numpy, scipy, pandas,
matplotlib), **bash** и zsh, **C/C++**;
- **Математика**: основы теории случайных процессов, машинное обучение,
построение критериев для проверки **гипотез**, численные методы,
моделирование (**метод отбора, MCMC, bootstrap**);
- **Вёрстка**: $\LaTeX$, Markdown, groff, HTML, CSS;
- **Общее**: чтение документации (на русском и английском), **git**,
**терминал** (vim, tmux, различные утилиты командной строки);

View File

@@ -66,7 +66,7 @@ box_name = "debian.jessie64.libvirt.box"
Описание виртуальной машины, на которой будет основная компиляция:
```
```ruby
# Master
master_node = {
:hostname => "master", :ip => "10.200.1.2", :memory => 1024, :cpu => 1
@@ -83,7 +83,7 @@ master_node = {
Описание второстепенной виртуальной машины:
```
```ruby
# List of slaves
slaves = [
{ :memory => 4096, :cpu => 4 },
@@ -97,7 +97,7 @@ slaves = [
Скрипт для автоматической установки зависимостей:
```
```ruby
$distcc_install = <<-SCRIPT
apt update
apt install -y make distcc gcc g++ tmux libz-dev git fakeroot build-essential ncurses-dev xz-utils libssl-dev bc flex libelf-dev bison time neofetch
@@ -106,13 +106,13 @@ SCRIPT
Старт конфигурации виртуальных машин:
```
```ruby
Vagrant.configure("2") do |config|
```
Конфигурация основной машины:
```
```ruby
# Master node's config
config.vm.box_check_update = false
config.vm.define master_node[:hostname] do |nodeconfig|
@@ -139,7 +139,7 @@ Vagrant.configure("2") do |config|
Конфигурация второстепенных машин:
```
```ruby
# Slaves configs
slaves.each_with_index do |slave, i|
config.vm.box_check_update = false
@@ -172,7 +172,7 @@ end
Далее необходимо подключиться к главной машине и распаковать исходники ядра[^3]:
```
```shell
vagrant ssh master
tar xvf linux-6.13.tar.gz
cd linux-6.13
@@ -181,7 +181,7 @@ cd linux-6.13
Создаем файл минимальной конфигурации
(с остальными вариантам можно ознакомиться командой `make help | less`):
```
```shell
make tinyconfig
```
@@ -190,7 +190,7 @@ make tinyconfig
Запускаем компиляцию с замером времени:
```
```shell
time -p make CC=gcc
```
@@ -199,13 +199,13 @@ time -p make CC=gcc
По смыслу, все тоже самое, только нужно указать distcc, на каких хостах
можно компилировать:
```sh
```shell
export DISTCC_HOSTS="localhost"
```
Запускаем компиляцию с замером времени:
```
```shell
time -p make CC="distcc gcc"
```
@@ -214,7 +214,7 @@ time -p make CC="distcc gcc"
Для запуска распределенной компиляции, нужно сначала запустить демон на
второй виртуальной машине. Для этого подключаемся к ней и запускаем его:
```
```shell
vagrant ssh slave-1
distccd --daemon --allow-private
```
@@ -230,7 +230,7 @@ distccd --daemon --allow-private
Теперь нужно добавить хост, чтобы на нем можно было удаленно компилировать.
Для этого на основной машине:
```
```shell
export DISTCC_HOSTS="localhost 10.200.1.3"
```
@@ -238,13 +238,13 @@ export DISTCC_HOSTS="localhost 10.200.1.3"
Запустим компиляцию на 5 потоках с замером времени:
```sh
```shell
time -p make -j5 CC="distcc gcc"
```
Мониторить компиляцию можно с помощью команды (на основной машине):
```
```shell
watch -n 1 distccmon-text
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 288 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

View File

@@ -1,10 +1,9 @@
# Математика
# Статистика
## 2024-10-30 [Немного про производящие функции](gen_fun.md)
## 2024-09-24 [Немного про Байесовскую статистику](baes.md)
## 2020-09-01 [Немного про проверку гипотез](stat-madness.md)
## 2025-05-30 [Немного про работу с файлами, numpy и предсказаниях](type-pred.md)

166
docs/maths/type-pred.md Normal file
View File

@@ -0,0 +1,166 @@
# Немного про работу с файлами, numpy и предсказаниях
## Введение
Известно, что файлы в памяти представлены последовательностью байтов.
Структурно, эта последовательность может быть разной. Она может
содержать только ASCII-текст, текст с любой кодировкой, сжатый архив,
mp3, etc. При взаимодействии с файлом (например, открыть файл
текстовым редактором), операционная система не смотрит на
т.н. **расширение файла**, её интересует *побайтовое* содержание
файла.
В Unix для определения типа файла есть утилита `file`. Как она
определяет тип я точно не знаю, но могу сказать, что частично метод
основан на *"заголовке"* файла (первых байтах).
Пример работы `file` на исполняемом файле:
```
./program: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, ...
```
Шестнадцатеричное представление (первые несколько строк) с помощью
`xxd`:
```console
00000000: 7f45 4c46 0201 0100 0000 0000 0000 0000 .ELF............
00000010: 0300 3e00 0100 0000 6010 0000 0000 0000 ..>.....`.......
00000020: 4000 0000 0000 0000 c036 0000 0000 0000 @........6......
00000030: 0000 0000 4000 3800 0d00 4000 1f00 1e00 ....@.8...@.....
```
В начале видно последовательность `ELF` -- формат исполняемых файлов в
Unix[1].
Возникает вопрос: **есть какой-то паттерн для различных типов файлов,
который можно увидеть, не считая специальных симвовол в *заголовке*?**
Можно усложнить вопрос: можно ли по какому-то обобщению (*сигнатуре*)
файла предсказать его тип? Попробуем это выяснить.
Для этого нужно решить следующие задачи:
1. Написать модуль (**на Си**), который по имени файла просчитывает
сигнатуру и возвращает её;
2. Посмотреть, как выглядят эти сигнатуры;
3. Попробовать обучить простую нейросеть.
## Как считать сигнатуру файла
Возьмем нулевую матрицу `M` размера 256х256, так как один байт это
число от 0 до 255. Считаем файл в память в виде последовательности
байтов. Теперь будем двигаться по последовательности с окном
размера 2. В этом окне первый элемент будет отвечать за номер строки,
а второй за номер столбца. И каждый раз с окном `(x, y)` будем
увеличивать элемент матрицы `M[x][y]` на единицу.
![](./assets/type-pred/file_sig.png)
## Причины использования Си
Если **кратко**: python очень медленный. Например, средний `wav`-файл
занимает около 10 мегабайт. Это порядка десяти миллионов байт, по
которым нужно пробежать и заполнить матрицу. А для обучения нейросети,
таких файлов должно быть много.
**Отдельный интерес**, также, представляет возможность написать модуль
для python на C, который умеет взаимодействовать с API библиотеки
NumPy.
## Чтение файлов в память
Для чтения файла в память, был написан модуль на Си, доступный
репозитории[2]. Здесь кратко опишу, как он работает.
В нем реализована функция `signature_from_filepath_by2`, которая
получает на вход два параметра: имя файла и уровень `verbose`. `by_2`
в названии обусловлено тем, что работа не с матрицами, а `n`-мерными
тензорами улучшает качество предсказания.
Функция `read_file` считывает файл в структуру `raw_data`, которая
представляет собой просто последовательность байтов и размер этой
последовательности. После этого функция `build_matrix` считывает по
этой струтуре сигнатуру и записывает в `matrix`.
Далее создается объект `PyObject *result`, представляющий собой
указатель на массив `NumPy` типа `uint32`. На его основе создается
динамический массив `result_data`.
Так как `matrix` лежит в памяти последовательно (ввиду того, что
она аллоцирована на стеке), то её можно просто скопировать в
`result_data`. После всего этого возвращается указатель `*result`.
Помимо этого в коде много второстепенных действий, которые требует API
Python для работы. Эти подробности я опустил, их можно увидеть в коде,
все достаточно предсказуемо.
## Пайплайн обучения нейросети
**Нюанс обучения нейросети**: так как получившиеся матрицы вышли очень
неравномерными, дополнительно они были размыты [*методом
Гаусса*](https://ru.wikipedia.org/wiki/%D0%A0%D0%B0%D0%B7%D0%BC%D1%8B%D1%82%D0%B8%D0%B5_%D0%BF%D0%BE_%D0%93%D0%B0%D1%83%D1%81%D1%81%D1%83).
Для обучения нейросети необходимо создать матрицу меток. Так как
предполагается, что нейросеть будет предсказывать различные типы
файлов, то матрица меток будет иметь размер `M*NxM`, где:
- `M` -- количество типов файлов
- `N` -- количество файлов в одном типе (берется минимальное из всех,
чтобы обучение было равномерным)
Для разбиения на тренировочную и обучающию выборки отлично подходит
функция `train_test_split` из модуля `sklearn.model_selection`.
Сам перцептрон будет иметь следующую архитектуру:
1. На входном слое будет 65536 нейронов (`256х256`). Функцией активации
будет `ReLu`-функция.
2. Скрытый слой будет иметь 512 нейронов и `sigmoid`-функцию активации.
3. На выходе будет столько нейронов, сколько типов файлов нужно будет
предсказать.
Для для задания `loss`-функции и оптимизатора:
```python
loss_fn = nn.CrossEntropyLoss()
optimizer = t.optim.SGD(model.parameters(), lr=1e-3)
```
Цикл обучения в данном случае состоял из 250 эпох.
Пайплайн обучения можно будет найти в репозитории
[проекта](https://github.com/rustbas/filetype-prediction), вместе с
инструкцией по воспроизведению результатов (кроме того факта, что
файлы различных типов нужно будет скачать самому).
## Результаты и картинки
Усреденные сигнатуры различных типов файлов можно увидеть ниже.
![](./assets/type-pred/heatmaps.png)
Также, показатели обучения:
![](./assets/type-pred/stats.png)
## Выводы
По итогу, можно сказать, что в некоторых случаях, *сигнатура* файла
является неплохим предиктором его типа.
Гипотетически, это можно использовать для следующих идей:
1. Восстановление частично поврежденных файлов, так как можно попытаться
угадать его структуру и восстановить её.
2. Определение исполняемых файлов при анализе вредоносного ПО.
3. Обнаружение скрытых данных (когда сигнатура файла и его тип не
соответствуют друг другу).
## Источники
1. [Википедия про ELF-формат](https://ru.wikipedia.org/wiki/Executable_and_Linkable_Format);
2. [Репозиторий проекта](https://github.com/rustbas/filetype-prediction);
3. [Основание идеи заметки](https://youtu.be/AUWxl0WdiNI?si=mklboGVUC-mZ-d1M);
1. [Пояснение про сигнатуру](https://youtu.be/4bM3Gut1hIk?si=zSGWLHKTKW7bStPb);
4. [Модули для Python](https://youtu.be/45TOazYbedI?si=jykTbnbjcyzTsN0r).

View File

@@ -3,12 +3,33 @@ site_url: https://rustbas.github.io/blog
repo_url: https://github.com/rustbas/blog
edit_uri: edit/main/docs/
theme:
name: terminal
palette: dark
name: material
palette:
- scheme: default
toggle:
icon: material/toggle-switch
name: Switch to dark mode
primary: green
- scheme: slate
toggle:
icon: material/toggle-switch-off-outline
name: Switch to light mode
primary: teal
features:
- revision.date
- revision.history
- navigation.side.hide
- navigation.instant # TODO: check troubles with TeX loading
- navigation.instant.progress
- header.autohide
icon:
repo: fontawesome/brands/git
font:
# text: Roboto
code: JetBrains Mono
# - revision.date
# - revision.history
# - navigation.side.hide
nav:
# - "Обо мне": 'index.md'
- "Математика": 'maths/index.md'
@@ -20,7 +41,7 @@ plugins:
lang: ["ru", "en"]
indexing: 'full'
- git-revision-date
markdown_extensions:
- pymdownx.arithmatex:
generic: true