Модуль 4 - Школа анализа инженерных данных
Проверка моделей и диагностика новых данных
Определим классификацию степеней износа элементов подшипника по пяти категориям. Диапазоны выбраны так, чтобы обеспечить практическую полезность диагностики: идеальное и хорошее состояние не требуют вмешательства, средний износ указывает на необходимость планового обслуживания, а сильный и критический износ требуют немедленной остановки и замены. Эта шкала будет использоваться для интерпретации результатов диагностики:
- от 0% до 10% — идеальное состояние;
- от 10% до 20% — хорошее состояние;
- от 20% до 50% — средний износ;
- от 50% до 75% — сильный износ;
- от 75% до 100% — критический износ.
Присоединение функций и библиотек
Подключим библиотеки, необходимые для загрузки модели и диагностики новых сигналов. MAT потребуется для чтения эталонных данных, WAV — для загрузки звуковых файлов с тестовыми сигналами. Serialization обеспечит чтение сохранённой модели из JLS-файла, а DecisionTree — выполнение диагностики.
#EngeePkg.purge()
#import Pkg
Pkg.add(["MAT", "Statistics", "DSP", "DecisionTree", "StatsBase", "Random"])
using MAT, Statistics, DSP, FFTW, DecisionTree, StatsBase, Random, Serialization, WAV
# Скачаем модель, которую обучили на прошлом шаге
using Downloads
src = "https://storage.yandexcloud.net/videohosting555/engee-ltc-school/%D0%BC%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C_%D0%BF%D0%BE%D0%B4%D1%88%D0%B8%D0%BF%D0%BD%D0%B8%D0%BA%D0%B0.jls"
dst = joinpath("$(@__DIR__)", "модель_подшипника.jls")
Downloads.download(src, dst)
Загрузим вспомогательные функции из внешних файлов, созданных на этапе обучения. вычислить_признаки.jl содержит функцию расчёта 54 диагностических признаков, идентичную использованной при обучении. media_player.jl обеспечит встроенный аудиоплеер для прослушивания тестовых сигналов.
include("вычислить_признаки.jl")
include("media_player.jl")
Загрузка модели
Загрузим обученные модели и все сопутствующие параметры из файла модель_подшипника.jls одной командой deserialize. Извлечём три модели Random Forest, векторы средних и СКО для нормализации признаков, параметры сегментации и эталонные значения амплитуды. После загрузки модель готова к диагностике без повторного обучения.
данные = deserialize("модель_подшипника.jls")
модель_внутр = данные.модель_внутр
модель_внеш = данные.модель_внеш
модель_ролик = данные.модель_ролик
средние = данные.средние_признаков
ско = данные.ско_признаков
длина_сегмента = данные.длина_сегмента
перекрытие = данные.перекрытие
частота_дискретизации = данные.частота_дискретизации
эталонный_rms = данные.эталонный_rms
эталонный_размах = данные.эталонный_размах
Деление на сегменты
Создадим функцию разделения сигнала на сегменты с теми же параметрами, что использовались при обучении. Это критически важно, поскольку признаки должны вычисляться на сегментах той же длины и с тем же перекрытием. Функция идентична той, что применялась в скрипте обучения.
function разделить_на_сегменты(сигнал, длина_сегмента, перекрытие)
шаг = Int(floor(длина_сегмента * (1 - перекрытие)))
сегменты = []
for i in 1:шаг:(length(сигнал) - длина_сегмента + 1)
push!(сегменты, сигнал[i:i+длина_сегмента-1])
end
return сегменты
end
Нормализация
Создадим функцию нормализации признаков с использованием средних и СКО, загруженных из файла модели. Она приводит новые признаки к тому же масштабу, на котором обучалась модель. Без этого шага предсказания будут некорректными из-за разного масштаба признаков.
function нормализовать(пр)
return (пр .- средние) ./ ско
end
Диагностика сегмента
Создадим функцию диагностики одного сегмента: вычисление признаков, нормализация и предсказание тремя моделями Random Forest. Результатом станет словарь с тремя значениями износа в процентах.
function диагностика_сегмента(сигнал, fs)
пр = нормализовать(вычислить_признаки(сигнал, fs))
м = reshape(пр, 1, :)
износ_внутр = DecisionTree.predict(модель_внутр, м)[1]
износ_внеш = DecisionTree.predict(модель_внеш, м)[1]
износ_ролик = DecisionTree.predict(модель_ролик, м)[1]
return Dict(
"Износ внутреннего кольца" => clamp(износ_внутр, 0, 100),
"Износ внешнего кольца" => clamp(износ_внеш, 0, 100),
"Износ ролика" => clamp(износ_ролик, 0, 100)
)
end
Диагностика полного сигнала
Создадим основную функцию диагностики, которая разбивает полный сигнал на сегменты, диагностирует каждый через диагностика_сегмента и усредняет результаты. Усреднение по сегментам повышает стабильность предсказания и снижает влияние случайных выбросов. Результат округляется до десятых долей процента.
function диагностика(полный_сигнал, fs)
сегменты = разделить_на_сегменты(полный_сигнал, длина_сегмента, перекрытие)
результаты = [диагностика_сегмента(сег, fs) for сег in сегменты]
ср_внутр = mean([р["Износ внутреннего кольца"] for р in результаты])
ср_внеш = mean([р["Износ внешнего кольца"] for р in результаты])
ср_ролик = mean([р["Износ ролика"] for р in результаты])
return Dict(
"Износ внутреннего кольца" => round(clamp(ср_внутр, 0, 100), digits=1),
"Износ внешнего кольца" => round(clamp(ср_внеш, 0, 100), digits=1),
"Износ ролика" => round(clamp(ср_ролик, 0, 100), digits=1))
end
Проверка на эталонных данных
Загрузим эталонные сигналы из MAT-файла для проверки качества модели на известных данных. Преобразуем их в векторы, аналогично тому, как это делалось при обучении. Эти сигналы будут использоваться как для прямой диагностики, так и для создания комбинаций с заданным процентом износа.
подшипник = matread("Bearing.mat")
Проверим качество работы модели на исходных сигналах и их комбинациях с известной степенью износа. Для каждого теста указан ожидаемый процент дефекта и соответствующая ему категория состояния согласно введённой классификации. Эталонные сигналы смешиваются по формуле норма + степень × (дефект − норма), что добавляет только дефектную составляющую к нормальному сигналу.
норма = vec(подшипник["normal"])
ролик = vec(подшипник["roller"])
внутр = vec(подшипник["inner"])
внеш = vec(подшипник["outer"])
Полностью исправный подшипник:
диагностика(норма, частота_дискретизации)
Полностью неисправный ролик:
диагностика(ролик, частота_дискретизации)
Полностью неисправное внутреннее кольцо:
диагностика(внутр, частота_дискретизации)
Полностью неисправное внешнее кольцо:
диагностика(внеш, частота_дискретизации)
Износ ролика 10%
⬇️
диагностика(норма + 0.10*(ролик-норма), частота_дискретизации)
Износ ролика 5%
⬇️
диагностика(норма + 0.05*(ролик-норма), частота_дискретизации)
Износ ролика 80%
Износ внешнего кольца 10%
Износ внутреннего кольца 10%
⬇️
диагностика(норма + 0.1*(внутр-норма) + 0.1*(внеш-норма) + 0.8*(ролик-норма), частота_дискретизации)
Износ всех элементов 50%
⬇️
диагностика(норма + 0.5*(внутр-норма) + 0.5*(внеш-норма) + 0.5*(ролик-норма), частота_дискретизации)
Износ ролика 10%
Износ внутреннего кольца 90%
⬇️
диагностика(норма + 0.9*(внутр-норма) + 0.1*(ролик-норма), частота_дискретизации)
Износ ролика 90%
Износ внутреннего кольца 20%
⬇️
диагностика(норма + 0.2*(внутр-норма) + 0.9*(ролик-норма), частота_дискретизации)
Износ ролика 5%
Износ внутреннего кольца 95%
⬇️
диагностика(норма + 0.95*(внутр-норма) + 0.05*(ролик-норма), частота_дискретизации)
Износ ролика 40%
Износ внешнего кольца 30%
Износ внутреннего кольца 30%
⬇️
диагностика(норма + 0.3*(внутр-норма) + 0.3*(внеш-норма) + 0.4*(ролик-норма), частота_дискретизации)
Износ ролика 60%
Износ внешнего кольца 70%
Износ внутреннего кольца 80%
⬇️
диагностика(норма + 0.8*(внутр-норма) + 0.7*(внеш-норма) + 0.6*(ролик-норма), частота_дискретизации)
Износ ролика 20%
Износ внешнего кольца 30%
Износ внутреннего кольца 50%
⬇️
диагностика(норма + 0.5*(внутр-норма) + 0.3*(внеш-норма) + 0.2*(ролик-норма), частота_дискретизации)
Модель демонстрирует точность диагностики, полностью соответствующую требованиям пятиуровневой классификации. Во всех без исключения проверенных сценариях категория состояния каждого элемента подшипника определена верно. Погрешности сосредоточены в пределах одной категории, что гарантирует правильность итогового заключения. Модель уверенно разделяет близкие по величине дефекты и стабильно детектирует слабый износ ролика даже на фоне доминирующих сигналов от колец.
Диагностика новых данных
Выполним диагностику новых данных с подшипников в различных состояниях. Данные хранятся в виде звуковых файлов формата wav. Для получение вектора чисел, используем функцию wavread(). Воспроизведём звук каждого подшипника и выполним их диагностику.
подшипник_1, fs = wavread("Подшипник_1.wav");
media_player("$(@__DIR__)/Подшипник_1.wav", mode="audio")
диагностика(подшипник_1, частота_дискретизации)
подшипник_2, fs = wavread("Подшипник_2.wav");
media_player("$(@__DIR__)/Подшипник_2.wav", mode="audio")
диагностика(подшипник_2, частота_дискретизации)
подшипник_3, fs = wavread("Подшипник_3.wav");
media_player("$(@__DIR__)/Подшипник_3.wav", mode="audio")
диагностика(подшипник_3, частота_дискретизации)
подшипник_4, fs = wavread("Подшипник_4.wav");
media_player("$(@__DIR__)/Подшипник_4.wav", mode="audio")
диагностика(подшипник_4, частота_дискретизации)
подшипник_5, fs = wavread("Подшипник_5.wav");
media_player("$(@__DIR__)/Подшипник_5.wav", mode="audio")
диагностика(подшипник_5, частота_дискретизации)
подшипник_6, fs = wavread("Подшипник_6.wav");
media_player("$(@__DIR__)/Подшипник_6.wav", mode="audio")
диагностика(подшипник_6, частота_дискретизации)
подшипник_7, fs = wavread("Подшипник_7.wav");
media_player("$(@__DIR__)/Подшипник_7.wav", mode="audio")
диагностика(подшипник_7, частота_дискретизации)
подшипник_8, fs = wavread("Подшипник_8.wav");
media_player("$(@__DIR__)/Подшипник_8.wav", mode="audio")
диагностика(подшипник_8, частота_дискретизации)
подшипник_9, fs = wavread("Подшипник_9.wav");
media_player("$(@__DIR__)/Подшипник_9.wav", mode="audio")
диагностика(подшипник_9, частота_дискретизации)
подшипник_10, fs = wavread("Подшипник_10.wav");
media_player("$(@__DIR__)/Подшипник_10.wav", mode="audio")
диагностика(подшипник_10, частота_дискретизации)
Разработанная модель акустической диагностики успешно решает задачу определения степени износа элементов подшипника по виброакустическому сигналу. На всех проверенных сценариях, от идеального состояния до критических комбинированных дефектов, модель показала стабильную точность в рамках заданной пятиуровневой классификации. Достигнутые результаты позволяют рассматривать данное решение как готовую основу для внедрения в системы промышленного мониторинга, что будет рассмотрено в следующем разделе.