Скачиваний:
0
Добавлен:
13.05.2026
Размер:
7.85 Кб
Скачать
import os
import skimage
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import minimize
from threading import Thread
import time
import math

#Создание класса-наследника класса Thread с возвращением элементов
class ThreadRV(Thread):

    def __init__(self, group=None, target=None, name=None,
        args=(), kwargs={}, Verbose=None):
        Thread.__init__(self, group, target, name, args, kwargs)
        self._return = None

    def run(self):
        if self._target is not None:
            self._return = self._target(*self._args, ** self._kwargs)

    def result(self):
        return self._return

#Функция вызова потоков
def thrd_call(trg, argnt1, argnt2, a):
    thread1 = ThreadRV(target=trg, args =argnt1)
    thread2 = ThreadRV(target=trg, args =argnt2)
    thread1.start()
    thread2.start()
    if a == False:
        thread2.join()
        thread1.join()
    elif a == True:
        thread1.join()
        thread2.join()
        return (thread1.result(), thread2.result())

#Функция считывания названий файлов
def f_name(s):
    lt = os.listdir(s)
    return lt

#Функция создания списков изображений
def img_read(ls, path):
    array = []
    for i in ls:
        array.append(np.array(skimage.io.imread(f'{path}/{i}')))
    return array

#Функция «упрощения» изображений
def img_symplify(array):
    new_array = array.copy()
    c = 0
    l = int(len(new_array[0])*len(new_array[0][0])/2)
    for i in new_array:
        i = i[1::2]
        i = np.reshape(i, (l, 3))
        new_array[c] = np.mean(i, axis=1, dtype=np.int16)
        c += 1
    return new_array

#Функция извлечения части из массива
def arr_cut(array, left_border, right_border):
    array_cut = array[left_border:right_border]
    return array_cut

#Функции вычисления значений гипотезы
#Для обучения
def h(th):
    hypothesis = 1/(1+np.exp(-(X_learn@th)))
    return hypothesis

#Для кроссвалидации
def h_cross(th):
    hypothesis = 1/(1+np.exp(-(X_cross@th)))
    return hypothesis

#Для тестов
def h_test(th):
    hypothesis = 1/(1+np.exp(-(X_test@th)))
    return hypothesis

#Функция вычисления значения функции стоимости
def J(th):
    summ = np.sum(Y_learn.T@np.log(h(th))+\
    	(np.subtract(one,Y_learn)).T@\
    	np.log(np.subtract(one,h(th))))
    return (-1)*summ/len(Y_learn)

#Функция вычисления значений производных
def dJ(theta):
    dif = (X_learn.T@(np.subtract(h(theta),Y_learn)))
    return np.divide(dif, len(Y_learn))

#Функция вычисления стоимости ошибок
def L(th):
    loss = np.log(1+np.exp(-1*np.multiply(h_test(th),Y_test.T)))\
    /math.log(2)
    return np.sum(loss)/len(Y_test)

#Функция вычисления производной функции стоимости ошибок
def dL(th):
    summ = np.multiply(h_test(th),Y_test.T)
    dif = np.exp(summ)/(np.exp(summ)*math.log(2)+math.log(2))
    return np.divide(dif, len(Y_test))

#Функция вычисления процента ошибок
def errors(th, border):
    H = h_test(th)
    H_sig = np.zeros(int(len(H)))
    c = 0
    for i in H:
        if i > border:
            H_sig[c] = 1
        c += 1
    err = np.equal(H_sig,Y_test)
    return (1-np.sum(err)/len(H_sig))*100

#Методика F_score
def F_score(th, border, arr):
    H = h_cross(th)
    H_sig = np.zeros(int(len(H)))
    c = 0
    for i in H:
        if i > border:
            H_sig[c] = 1
        c += 1
    #Истинноположительные
    TP = np.sum(np.logical_and(H_sig,arr))
    #Ложноположительные
    FP = np.sum(np.logical_not(np.logical_or(np.logical_not(H_sig),arr)))
    #Ложноотрицательные
    FN = np.sum(np.logical_and(np.logical_not(H_sig),arr))
    #Метрика Percision (точность)
    P = TP/(FP+TP)
    #Метрика Recall (полнота)
    R = TP/(FN+TP)
    #Метрика F1 
    return (2*P*R)/(P+R)

#Очистка окна консоли
os.system('cls')

#Запуск таймера
t1 = time.perf_counter_ns()

#Создание списков названий файлов в папках
trees_list, no_trees_list = thrd_call(f_name,\
    ("Trees",), ("NoTrees",), True)

#Создание списков изображений в папке
trees_img_list, no_trees_img_list = thrd_call(img_read,\
    (trees_list, "Trees"), (no_trees_list, "NoTrees"), True)

#Упрощение данных
trees_img_list, no_trees_img_list = thrd_call(img_symplify,\
    (trees_img_list,), (no_trees_img_list,), True)

#Создание массива параметров
X = np.vstack((np.array(trees_img_list),\
    np.array(no_trees_img_list)))
X = X.astype('float32')/255
X = np.hstack((np.ones((len(X),1),dtype=np.float16),X))

#Создание массива результатов
Y = np.hstack((np.ones(len(X)//2),
    np.zeros(len(X)//2)))

#Перемешивание массивов параметров и результатов
permutation = np.random.permutation(len(X))
X = X[permutation]
Y = Y[permutation]

#Разделение на части
##Выделение данных на обучение
X_learn, Y_learn = thrd_call(arr_cut,\
    (X,0,6400), (Y,0,6400), True)
##Выделение данных на кроссвалидацию
X_cross, Y_cross = thrd_call(arr_cut,\
    (X,6400,8400), (Y,6400,8400), True)
##Выделение данных на тестирование
X_test, Y_test = thrd_call(arr_cut,\
    (X,8400,10400), (Y,8400,10400), True)

#Создание массива коэффициентов
theta = np.zeros(len(X_learn[0]))
one = np.ones(len(Y_learn))

#Реализация вычислений с сохранением результата
if os.path.isfile("minimize_res.txt") == False:
    #Вычисление коэффициентов гипотезы
    J_min = minimize(J,theta,method='BFGS',jac=dJ)
    #Запись результатов в файл
    f = open("minimize_res.txt", 'wt')
    for i in J_min.x:
        f.write(str(i)+' ')
    f.write('\n'+str(J_min.fun))
    f.close()
    line = J_min.x
elif os.path.isfile("minimize_res.txt") == True:
    #Считывание результатов из файла
    f = open("minimize_res.txt", 'rt')
    line = f.read().split(' ')
    line = np.array(line[0:-1], dtype=np.float64)
    f.close()

#Определение оптимального порога
metric = [[i/10 for i in range(0,11)],[]]

for i in metric[0]:
    metric[1].append(F_score(line,i,Y_cross))
metric[1][-1] = 0

#Вывод результатов на экран
print(f'| border |', end="")
for i in metric[0]:
    print(f' {i:.5f} ', end="|")
print(f'\n| Fscore |', end="")
for i in metric[1]:
    print(f' {i:.5f} ', end="|")
max_Fscore = max(metric[1])
optimal_brd = metric[0][metric[1].index(max_Fscore)]
print(f'\nOptimal border is {optimal_brd:.5f} \
at F-score {max_Fscore:.5f}.')

#Расчёт процента ошибок
print(f'\nTotal percentage of errors at optimal border: \
{errors(line, optimal_brd):.2f}%.\
\nF-score at optimal border: \
{F_score(line,optimal_brd,Y_test):.5f}.')

#Вывод времени выполнения программы
print(f'\nTotal program execution time: \
{(time.perf_counter_ns()-t1)/10**9:.5f} seconds.')
Соседние файлы в папке лабы