Для решения задач машинного обучения предлагается метрика, основанная на формуле отношения сигнала к шуму, SNR:

Для приложений в сфере информационных технологий, измерительной технике, где существует проблема выбора объективного количественного критерия помехоустойчивости устройств применяется отношение сигнала к шуму, SNR.

Предложенная формула SNR инвариантна относительно любых линейных преобразований наборов a(i) (инвариантность по масштабу и сдвигу) и не зависит от числа гранулирования M для множества точек нормального гауссова распределения. Квадратичные формы S и N положительно определены для произвольных наборов a(i).

Вывод формулы осуществляется из фрактала «пыль Кантора». Из вывода формулы и опыта применения, уместно приложение в сложной системе, когда упорядоченность причинно-следственных связей элементов внутри сложной системы не значима, а заметны нелинейные тенденции к самоорганизации данных.

Отношение сигнала к шуму обратно пропорционально числу степеней свободы сложной системы. Характерны для системы максимальные и минимальные значения SNR, последовательное их чередование.

Для применения метрики в машинном обучении критически важна оптимизация по времени расчёта. Исходя из опыта, предлагается следующий программный продукт.

# SNR, автор Александр Макарик(с)
import numpy as np
from numba import njit

@njit(fastmath=True)
def calcChisl(m):
    n=m.size-1
    s=0
    for i in range (2, n - 1):
        s = s + m[i] * (2 * m[i] - m[i + 2] - m[i - 2])
        #'s = s + massivOfElements(i] * (massivOfElements2(i] - massivOfElements(i + 2] - massivOfElements(i - 2])

            #'для замкнутого контура
    s = s + m[0] * (2 * m[0] - m[2] - m[n - 1])
    s = s + m[1] * (2 * m[1] - m[3] - m[n])

    s = s + m[n - 1] * (2 * m[n - 1] - m[0] - m[n - 3])
    s = s + m[n] * (2 * m[n] - m[1] - m[n - 2])
    return s
    
@njit(fastmath=True)
def calcZnam(m):
    n=m.size-1
    s=0
    for i in range (2, n - 1):
        s = s + m[i] * (6 * m[i] - 4 * m[i + 1] + m[i + 2] + m[i - 2] - 4 * m[i - 1])
        # 's = s + massivOfElements(i] * (massivOfElements6(i] - massivOfElements4(i + 1] + massivOfElements(i + 2] + massivOfElements(i - 2] - massivOfElements4(i - 1])

            #'для замкнутого контура
    s = s + m[0] * (6 * m[0] - 4 * m[1] + m[2] + m[n - 1] - 4 * m[n])
    s = s + m[1] * (6 * m[1] - 4 * m[2] + m[3] + m[n] - 4 * m[0])

    s = s + m[n - 1] * (6 * m[n - 1] - 4 * m[n] + m[0] + m[n - 3] - 4 * m[n - 2])
    s = s + m[n] * (6 * m[n] - 4 * m[0] + m[1] + m[n - 2] - 4 * m[n - 1])

    #        'для незамкнутого контура
    #        's = s + m(1] * (3 * m(1] - 4 * m(2] + m(3])
    #        's = s + m(2] * (7 * m(2] - 4 * m(1] + -4 * m(3] + m(4])

    #        's = s + m(n - 1] * (7 * m(n - 1] - 4 * m(n - 2] - 4 * m(n] + m(n - 3])
    #        's = s + m(n] * (3 * m(n] - 4 * m(n - 1] + m(n - 2])
    return s

def calcSNR(arr):
    #print(arr[0:10])
    z=calcZnam(arr)
    #if z!=0:
    a=calcChisl(arr)/z
    #else:
    #    a=0
    if a<0:print ('znam=',znam)
    if a<0:print ('Chisl=',znam)
    return a
    
def snrVectorSlow(arr,deslength):
    vSNR=np.zeros(arr.size-deslength)

    for i in range(arr.size-deslength):
        b=arr[i:i+deslength]
        # vSNR = np.append(vSNR, SNR.calcSNR(b])
        vSNR[i]= calcSNR(b)
    return vSNR
    
@njit(fastmath=True)
def snrChislVector(m):
    chisl=np.zeros(m.size)
    n=m.size-1
    for i in range (2, n - 1):
        chisl[i] = m[i] * (2 * m[i] - m[i + 2] - m[i - 2])
        #'s = s + massivOfElements(i] * (massivOfElements2(i] - massivOfElements(i + 2] - massivOfElements(i - 2])

            #'для замкнутого контура
    chisl[0] = m[0] * (2 * m[0] - m[2] - m[n - 1])
    chisl[1] = m[1] * (2 * m[1] - m[3] - m[n])

    chisl[n-1] = m[n - 1] * (2 * m[n - 1] - m[0] - m[n - 3])
    chisl[n] = m[n] * (2 * m[n] - m[1] - m[n - 2])
    return chisl
    
@njit(fastmath=True)
def snrZnamVector(m):
    
    n=m.size-1
    
    k=m
    
    tempV=np.zeros(m.size)
    for i in range (2, n - 1):
        tempV[i] = k[i] * (6 * k[i] - 4 * k[i + 1] + k[i + 2] + k[i - 2] - 4 * k[i - 1])
    
    tempV[0] = k[0] * (6 * k[0] - 4 * k[1] + k[2] + k[n - 1] - 4 * k[n])
    tempV[1] = k[1] * (6 * k[1] - 4 * k[2] + k[3] + k[n] - 4 * k[0])

    tempV[n - 1] = k[n - 1] * (6 * k[n - 1] - 4 * k[n] + k[0] + k[n - 3] - 4 * k[n - 2])
    tempV[n] = k[n] * (6 * k[n] - 4 * k[0] + k[1] + k[n - 2] - 4 * k[n - 1])
    
    znam=tempV #*9
    return znam

@njit(fastmath=True)
def snrVector(arr,deslength):
    vSNR=np.zeros(arr.size-deslength)
    b=arr[0:deslength]
    chisl=snrChislVector(b)
    znam=snrZnamVector(b)
    vSNR[0]=np.sum(chisl)/np.sum(znam)
    
    n=deslength-1
    #d=arr[0:deslength]
    for k in range(1,arr.size-deslength):
        if (k%1000==0):print(k)
        d=arr[k:k+deslength]
        #chisl=np.delete(chisl,0)
        
        chisl=chisl[1:chisl.size]  #так быстрее
        chisl = np.append(chisl, 0) # просто в конец добавляем элемент
        
        chisl[1] = d[1] * (2 * d[1] - d[3] - d[n])
        i = n - 2
        chisl[i] = d[i] * (2 * d[i] - d[i + 2] - d[i - 2])
        chisl[n - 1] = d[n - 1] * (2 * d[n - 1] - d[0] - d[n - 3])
        chisl[n] = d[n] * (2 * d[n] - d[1] - d[n - 2])
        
        
        znam=znam[1:znam.size]  #так быстрее
        znam = np.append(znam, 0) # просто в конец добавляем элемент
        
        znam[0] = d[0] * (6 * d[0] - 4 * d[1] + d[2] + d[n - 1] - 4 * d[n])
        znam[1] = d[1] * (6 * d[1] - 4 * d[2] + d[3] + d[n] - 4 * d[0])

        znam[i] = d[i] * (6 * d[i] - 4 * d[i + 1] + d[i + 2] + d[i - 2] - 4 * d[i - 1])
        znam[n - 1] = d[n - 1] * (6 * d[n - 1] - 4 * d[n] + d[0] + d[n - 3] - 4 * d[n - 2])
        znam[n] = d[n] * (6 * d[n] - 4 * d[0] + d[1] + d[n - 2] - 4 * d[n - 1])
        
        vSNR[k]=np.sum(chisl)/np.sum(znam)
        
        
    
    return vSNR
    
   
@njit(fastmath=True)
def snrVectorFastest(arr,deslength):
    vSNR=np.zeros(arr.size-deslength)
    d=arr[0:deslength]
    chisl=np.sum(snrChislVector(d))
    znam=np.sum(snrZnamVector(d))
    
    kkk=chisl/znam
    
    vSNR[0]=kkk
    
    n=deslength-1
    
    v=np.zeros(6)
    
    # chisl[i] = m[i] * (2 * m[i] - m[i + 2] - m[i - 2])
    
    for k in range(1,arr.size-deslength):
        # if (k%1000==0):print(k)
        
        v[0] = d[0] * (2 * d[0] - d[2] - d[n-1])
        v[1] = d[1] * (2 * d[1] - d[3] - d[n])
        v[2] = d[2] * (2 * d[2] - d[4] - d[0])   #его не обязательно...cчитать потом
        
        i = n - 2
        # v[3] = d[i] * (2 * d[i] - d[i + 2] - d[i - 2])  #его удалять не надо...!!! но добавить надо
        v[4] = d[n - 1] * (2 * d[n - 1] - d[0] - d[n - 3])
        v[5] = d[n] * (2 * d[n] - d[1] - d[n - 2])
        
        chisl=chisl-v[0]-v[1]-v[2]-v[4]-v[5]
        
        
        #tempV[i] = k[i] * (6 * k[i] - 4 * k[i + 1] + k[i + 2] + k[i - 2] - 4 * k[i - 1])
        
        v[0] = d[0] * (6 * d[0] - 4 * d[1] + d[2] + d[n - 1] - 4 * d[n])
        v[1] = d[1] * (6 * d[1] - 4 * d[2] + d[3] + d[n] - 4 * d[0])
        v[2] = d[2] * (6 * d[2] - 4 * d[3] + d[4] + d[0] - 4 * d[1])   #его не обязательно считать потом


        # v[3] = d[i] * (6 * d[i] - 4 * d[i + 1] + d[i + 2] + d[i - 2] - 4 * d[i - 1])  #его удалять не надо...но добавить надо
        v[4] = d[n - 1] * (6 * d[n - 1] - 4 * d[n] + d[0] + d[n - 3] - 4 * d[n - 2])
        v[5] = d[n] * (6 * d[n] - 4 * d[0] + d[1] + d[n - 2] - 4 * d[n - 1])
        
        znam=znam-v[0]-v[1]-v[2]-v[4]-v[5]
        
        d=arr[k:k+deslength]
        
        v[0] = d[0] * (2 * d[0] - d[2] - d[n-1])
        v[1] = d[1] * (2 * d[1] - d[3] - d[n])
        
        v[3] = d[i] * (2 * d[i] - d[i + 2] - d[i - 2])  #его удалять не надо...!!! но добавить надо
        v[4] = d[n - 1] * (2 * d[n - 1] - d[0] - d[n - 3])
        v[5] = d[n] * (2 * d[n] - d[1] - d[n - 2])
        
        chisl=chisl+ v[0] + v[1]+v[3]+v[4]+v[5]
        
        
        v[0] = d[0] * (6 * d[0] - 4 * d[1] + d[2] + d[n - 1] - 4 * d[n])
        v[1] = d[1] * (6 * d[1] - 4 * d[2] + d[3] + d[n] - 4 * d[0])
        #v[2] = d[2] * (6 * d[2] - 4 * d[3] + d[4] + d[0] - 4 * d[1])   #его не обязательно считать потом


        v[3] = d[i] * (6 * d[i] - 4 * d[i + 1] + d[i + 2] + d[i - 2] - 4 * d[i - 1])  #его удалять не надо...но добавить надо
        v[4] = d[n - 1] * (6 * d[n - 1] - 4 * d[n] + d[0] + d[n - 3] - 4 * d[n - 2])
        v[5] = d[n] * (6 * d[n] - 4 * d[0] + d[1] + d[n - 2] - 4 * d[n - 1])
        
        znam=znam + v[0] + v[1]+v[3]+v[4]+v[5]
        
        vSNR[k]=chisl/znam
        
    
    return vSNR

Комментарии (7)


  1. orekh
    11.04.2024 07:28
    +2

    Ничего не понятно.


    1. Vital18 Автор
      11.04.2024 07:28

      Инструмент для решения задач.


  1. ValeriyPushkarev
    11.04.2024 07:28

    1. Vital18 Автор
      11.04.2024 07:28

      В статье оригинальная формула для SNR.


      1. ValeriyPushkarev
        11.04.2024 07:28
        +1

        А где хотя-бы векторизация? Да и сам SNR+Determination - неудачные метрики


  1. sawabear_a
    11.04.2024 07:28

    Хотелось бы код в скрытые блоки. И добавить к блокам объяснение


  1. Vital18 Автор
    11.04.2024 07:28

    Цель публикации состоит в продвижении фрактальной метрики в качестве инструмента в обработке данных. Метрика, которая выводится из первых принципов и является физической характеристикой - связанность.