Технологии не стоят на месте, и вот мы уже вступили в эпоху, когда люди начали применять искусственные нейронные сети. Люди некоторых профессий даже начали чувствовать конкуренцию со стороны программных продуктов. Конечно, это происходит далеко не во всех отраслях, но процесс уже пошел, и я думаю вряд ли это удастся остановить. Проблема в том, что позволить себе новые технологии могут только крупные компании, которые таким образом оптимизируют расходы на зарплату работников. В малом и среднем бизнесе прогресс не очень большой. Они по большей части придерживаются классических методов, в которых основную работу выполняют люди, а компьютеры используются в основном для бухгалтерии, учета, выполнения задач заданных статическими правилами и простых операций вроде работы в Word и Excel. Но почему сложилась такая ситуация?

Можно строить разные предположения на этот счет. Возможно сказывается инерция мышления, которая заставляет людей мыслить шаблонами, хотя это и не всегда плохо. Я хотел бы мыслить шаблонами человека, который смог заработать миллион долларов, и работает над получением миллиарда. Но даже такие люди иногда сталкиваются с пределом, который они переступить не в состоянии. Или сталкиваются со слишком медленным по их мнению ростом. Очевидно, что в этом случае волей неволей приходится что-то менять. Приходится начинать делать то, о чем раньше было сложно подумать. Например, приобщаться к вершине технического прогресса, чем на данный момент являются нейронные сети. Но каков порог входа на этом направлении, и что реально можно при этом сделать? Я попробовал это понять.

Конечно, я исследовал отрасль машинного обучения не как владелец бизнеса, так как к сожалению им не обзавелся. Я начал изучать как простой работник, который захотел устроиться в компанию занимающуюся нейросетями. Выяснилось что вакансий в этой области совсем мало, а пройти по тем что есть просто нереально. Неужели решение задач с помощью нейронных сетей настолько непопулярно, что много специалистов для этого не требуется? Или нейронные сети просто не способны дать такой уровень дохода, при котором их внедрение вообще имеет смысл? Попробуем все таки изучить вопрос чисто теоретически, и выяснить на что нейронные сети способны на данный момент.

Генерация идей

Любое дело начинается с идеи, которую необходимо воплотить в реальность. Идею необходимо придумать, узнать как можно ее реализовать, понять какая от этого будет польза, выяснить какие в результате возникнут проблемы, и так далее. Звучит уже сложно. Очевидно что на текущем уровне развития нейросетям с этим не справиться. Приходится помогать им в этом. Давайте попробуем создать идею для бизнеса с помощью широко известного чат-бота ChatGPT.

Придумай новую бизнес-идею для реализации в области ресторанного бизнеса

Конечно! Одна из новых бизнес-идей для ресторанного бизнеса может быть создание роботизированного ресторана. В таком ресторане заказы принимаются через приложение на смартфоне, а затем блюда готовятся и доставляются клиентам роботами-курьерами. Такой подход позволит снизить затраты на персонал и увеличить эффективность обслуживания, а также создать неповторимую атмосферу в ресторане. Кроме того, роботы-повара могут точно следовать рецептам и готовить блюда с одинаковым качеством каждый раз. Это может привлечь клиентов, которые ценят качество и надежность.

Для этой идеи потребуется иметь роботов, а они сейчас не существуют. Придумай другую идею в области ресторанного бизнеса.

Конечно! Еще одна идея для ресторанного бизнеса - это создание вегетарианского ресторана. Сейчас все больше людей переходят на вегетарианскую диету, и это может быть хорошим бизнесом. Вегетарианский ресторан может предлагать разнообразные блюда, которые не содержат мясо, но при этом вкусные и питательные. Кроме того, вегетарианский ресторан может привлечь клиентов, которые страдают от аллергий или не могут употреблять определенные продукты. Также можно предложить вегетарианские варианты для популярных блюд, таких как бургеры или пицца. Вегетарианский ресторан может стать местом, где люди могут насладиться вкусной и здоровой едой в уютной и дружественной атмосфере.

К сожалению, вегетарианцев не так много, как клиентов с обычным вкусом. Придумай другую идею в области ресторанного бизнеса.

Хорошо, я могу предложить идею создания ресторана, специализирующегося на здоровом питании. В последнее время все больше людей обращают внимание на свое здоровье и стремятся к здоровому образу жизни. Ресторан здорового питания может предлагать блюда, которые не только вкусны, но и полезны для здоровья. В меню можно включить блюда, приготовленные из свежих овощей, фруктов, зелени и других натуральных продуктов. Также можно предложить готовые комплексные обеды, которые содержат все необходимые питательные вещества и витамины. Такой ресторан может привлечь не только людей, следящих за своим здоровьем, но и тех, кто хочет попробовать что-то новое и интересное. Кроме того, можно предложить услуги консультанта по здоровому питанию, который поможет посетителям выбрать блюда, наиболее подходящие для их потребностей и предпочтений.

Это уже лучше, но еда в таком ресторане будет очень дорогой. А это значит что мало клиентов сможет ее позволить. Придумай другую идею в области ресторанного бизнеса.

Понимаю вашу озабоченность по поводу стоимости блюд в ресторане здорового питания. Могу предложить идею ресторана с бюджетной и здоровой едой. Этот ресторан может предлагать блюда, приготовленные из доступных и недорогих ингредиентов, которые содержат все необходимые питательные вещества и витамины. Кроме того, можно использовать инновационные технологии, такие как вертикальное фермерство, чтобы получать свежие овощи и фрукты по более низкой цене. Привлекательный дизайн интерьера и обслуживание на высоком уровне также могут привлечь больше клиентов.

На этом я остановился, так как я не очень разбираюсь в вертикальном фермерстве, мне сложно понять имеет ли смысл интегрироваться с представителями фермерского хозяйства, и так далее. Тем не менее понятно что нейронные сети уже можно использовать для генерации идей. Для интереса я попросил бота придумать план по захвату мира, на что он дал вполне вменяемый ответ. Разумеется план был настолько же нереалистичным как и возможность достижения поставленной цели. Тем не менее стало понятно в каком направлении надо начинать делать шаги. Но если ваши цели не настолько глобальны, то пользу от этого также можно попробовать извлечь.

Исполнение задач

Компьютеры для того и созданы чтобы выполнять задания. Люди задают программу, а компьютер ее исполняет. Разумеется, не стоит говорить о роботах, тем более о роботах человекоподобных. Они дорогие и на данный момент несовершенные. Давайте остановимся пока всего лишь на обработке информации, а для этого ничего особенного и не надо. Подойдет практически любой компьютер достаточной конфигурации. В некоторых случаях потребуется иметь видеокарту, но сейчас, после окончания майнинг-бума это вообще не проблема. Так что развивать эту тему дальше не будем, здесь и так все понятно.

Создание нейронных сетей

Может показаться что на этом моменте как раз и возникнут проблемы. Чтобы создавать и использовать нейронные сети придется приобрести соответствующие знания и опыт. Но так как тема интересная, то и желающих этим заниматься очень много. Кое кто даже пробовал что-то сделать. Например, я имею небольшой опыт, и могу построить некоторые виды нейронных сетей, но мои знания не продвинулись дальше учебных задач. А реальных задач для себя на тот момент я придумать не смог. Но это было несколько лет назад, сейчас же появился реально хороший помощник - ChatGPT, давайте попробуем понять на что способен простой программист, который захочет им вооружиться.

Перед тем как приступать к сложным задачам я не поверил в возможности бота и начал с простейшей школьной задачи.

Дай код программы где происходит сортировка массива методом пузырька

Hidden text
def bubble_sort(arr):
    n = len(arr)
    
    # Проходим по всем элементам массива
    for i in range(n):
        
        # Последние i элементов уже отсортированы,
        # поэтому мы можем их пропустить
        for j in range(n - i - 1):
            
            # Если текущий элемент больше следующего,
            # меняем их местами
            if arr[j] > arr[j + 1]:
                arr[j], arr[j + 1] = arr[j + 1], arr[j]
    
    return arr

Очень похоже на правду. Я этот код не запускал, но сомнений в его работоспособности нет. Переходим к более сложной задаче.

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

Hidden text
import random
import numpy as np

# Определение функции для подбора
def func(x, a, b, c):
    return a * np.sin(b * x) + c

# Генерация начальной популяции
def generate_population(population_size, num_params):
    population = []
    for i in range(population_size):
        individual = []
        for j in range(num_params):
            individual.append(random.uniform(-10, 10))
        population.append(individual)
    return population

# Определение функции приспособленности (fitness function)
def fitness_function(individual, x, y):
    a, b, c = individual
    y_pred = func(x, a, b, c)
    error = np.mean(np.abs(y - y_pred))
    fitness = 1 / (error + 1e-6)
    return fitness

# Определение оператора скрещивания (crossover operator)
def crossover(parent1, parent2):
    child = []
    for i in range(len(parent1)):
        if random.random() < 0.5:
            child.append(parent1[i])
        else:
            child.append(parent2[i])
    return child

# Определение оператора мутации (mutation operator)
def mutate(individual, mutation_rate):
    for i in range(len(individual)):
        if random.random() < mutation_rate:
            individual[i] += random.uniform(-1, 1)
    return individual

# Определение генетического алгоритма
def genetic_algorithm(x, y, population_size=100, num_generations=100, mutation_rate=0.1):
    num_params = 3
    population = generate_population(population_size, num_params)

    for i in range(num_generations):
        # Вычисление приспособленности для каждого индивида
        fitness_scores = []
        for individual in population:
            fitness_scores.append(fitness_function(individual, x, y))

        # Выбор родителей
        parent1, parent2 = random.choices(population, weights=fitness_scores, k=2)

        # Скрещивание родителей и мутация потомства
        child = crossover(parent1, parent2)
        child = mutate(child, mutation_rate)

        # Замена наименее приспособленного индивида потомством
        fitness_scores = []
        for individual in population:
            fitness_scores.append(fitness_function(individual, x, y))
        min_fitness_idx = np.argmin(fitness_scores)
        population[min_fitness_idx] = child

    # Возвращение наилучшего индивида
    fitness_scores = []
    for individual in population:
        fitness_scores.append(fitness_function(individual, x, y))
    best_individual_idx = np.argmax(fitness_scores)
    return population[best_individual_idx]

# Пример использования
x = np.linspace(-10, 10, 100)
y = func(x, 2, 3, 1) + np.random.normal(0, 1, 100)
best_individual = genetic_algorithm(x, y)
print("Best individual:", best_individual)

Очень даже неплохо. Я создавал такие программы и вижу что все на месте. А как насчет других языков программирования?

А теперь то же самое на java

Hidden text
import java.util.Arrays;
import java.util.Random;

public class GeneticAlgorithm {
    private static final double MUTATION_RATE = 0.1;
    private static final int POPULATION_SIZE = 100;
    private static final int NUM_GENERATIONS = 100;

    public static double[] geneticAlgorithm(int[][] points) {
        int numPoints = points.length;
        double[][] population = initializePopulation(numPoints);
        double[] fitness = calculateFitness(population, points);
        for (int i = 0; i < NUM_GENERATIONS; i++) {
            double[][] newPopulation = new double[POPULATION_SIZE][numPoints + 1];
            for (int j = 0; j < POPULATION_SIZE; j++) {
                double[] parent1 = selectParent(population, fitness);
                double[] parent2 = selectParent(population, fitness);
                double[] child = crossover(parent1, parent2);
                child = mutate(child);
                newPopulation[j] = child;
            }
            population = newPopulation;
            fitness = calculateFitness(population, points);
        }
        double[] bestIndividual = getBestIndividual(population, fitness);
        return bestIndividual;
    }

    private static double[][] initializePopulation(int numPoints) {
        double[][] population = new double[POPULATION_SIZE][numPoints + 1];
        for (int i = 0; i < POPULATION_SIZE; i++) {
            for (int j = 0; j < numPoints; j++) {
                population[i][j] = getRandomCoefficient();
            }
            population[i][numPoints] = getRandomConstant();
        }
        return population;
    }

    private static double getRandomCoefficient() {
        Random random = new Random();
        return random.nextDouble() * 10 - 5;
    }

    private static double getRandomConstant() {
        Random random = new Random();
        return random.nextDouble() * 100 - 50;
    }

    private static double[] calculateFitness(double[][] population, int[][] points) {
        double[] fitness = new double[POPULATION_SIZE];
        for (int i = 0; i < POPULATION_SIZE; i++) {
            double[] individual = population[i];
            double error = calculateError(individual, points);
            fitness[i] = 1 / (error + 1);
        }
        return fitness;
    }

    private static double calculateError(double[] individual, int[][] points) {
        double error = 0;
        for (int i = 0; i < points.length; i++) {
            int x = points[i][0];
            int y = points[i][1];
            double predictedY = evaluateFunction(individual, x);
            error += Math.pow(predictedY - y, 2);
        }
        return error;
    }

    private static double evaluateFunction(double[] individual, double x) {
        double y = 0;
        for (int i = 0; i < individual.length - 1; i++) {
            y += individual[i] * Math.pow(x, i);
        }
        y += individual[individual.length - 1];
        return y;
    }

    private static double[] selectParent(double[][] population, double[] fitness) {
        Random random = new Random();
        int index1 = random.nextInt(POPULATION_SIZE);
        int index2 = random.nextInt(POPULATION_SIZE);
        if (fitness[index1] > fitness[index2]) {
            return population[index1];
        } else {
            return population[index2];
        }
    }

    private static double[] crossover(double[] parent1, double[] parent2) {
        double[] child = new double[parent1.length];
        Random random = new Random();
        int crossoverPoint = random.nextInt(parent1.length);
        for (int i = 0; i < crossoverPoint; i++) {
            child[i] = parent1[i];
        }
        for (int i = crossoverPoint; i < parent1.length; i++) {
            child[i] = parent2[i];
        }
        return child;
    }

    private static double[] mutate(double[] child) {
        Random random = new Random();
        for (int i = 0; i < child.length; i++) {
            if (random.nextDouble() < MUTATION_RATE) {
                child[i] += random.nextDouble() * 2 - 1;
            }
        }
        return child;
    }

    private static double[] getBestIndividual(double[][] population, double[] fitness) {
        int index = 0;
        for (int i = 1; i < POPULATION_SIZE; i++) {
            if (fitness[i] > fitness[index]) {
                index = i;
            }
        }
        return population[index];
    }

    public static void main(String[] args) {
        int[][] points = {{0, 1}, {1, 4}, {2, 9}, {3, 16}, {4, 25}};
        double[] bestIndividual = geneticAlgorithm(points);
        System.out.println("Best individual: " + Arrays.toString(bestIndividual));
    }
}

Тоже неплохо. Все на месте. Продолжаем исследовать возможности.

А теперь дай генетический алгоритм на C++

There was an error in my head, I seem to have broken down :(
Repeat the query later and/or make it smaller

К сожалению, в этот момент в боте что-то сломалось. Увы, даже этот чат-бот далеко не совершенен. Я повторил запрос позже, пришлось сбросить историю разговора, а при повторном запросе я забыл упомянуть про массив точек. Бот создал код на C++, но реализация была классической, подбора по точкам уже нет. ChatGPT реально способен генерировать код на основе заданного ему контекста. Он выдает вовсе не шаблонные примеры.

Hidden text
#include <iostream>
#include <vector>
#include <cstdlib>
#include <ctime>
#include <cmath>

using namespace std;

class Individual{
public:
    vector<int> chromosome;
    int fitness;
    Individual(int chromosomeLength){
        for(int i = 0; i < chromosomeLength; i++){
            chromosome.push_back(rand()%2);
        }
        fitness = -1;
    }
};

class Population{
public:
    vector<Individual> individuals;
    Population(int populationSize, int chromosomeLength){
        for(int i = 0; i < populationSize; i++){
            individuals.push_back(Individual(chromosomeLength));
        }
    }
};

class GeneticAlgorithm{
public:
    double mutationRate;
    int tournamentSize;
    bool elitism;
    GeneticAlgorithm(double mutationRate, int tournamentSize, bool elitism){
        this->mutationRate = mutationRate;
        this->tournamentSize = tournamentSize;
        this->elitism = elitism;
    }
    void evaluate(Individual &individual){
        int fitness = 0;
        for(int i = 0; i < individual.chromosome.size(); i++){
            if(individual.chromosome[i] == 1){
                fitness++;
            }
        }
        individual.fitness = fitness;
    }
    void evaluatePopulation(Population &population){
        for(int i = 0; i < population.individuals.size(); i++){
            evaluate(population.individuals[i]);
        }
    }
    Individual tournamentSelection(Population &population){
        Population tournamentPopulation(0, 0);
        for(int i = 0; i < tournamentSize; i++){
            int randomIndex = rand()%population.individuals.size();
            tournamentPopulation.individuals.push_back(population.individuals[randomIndex]);
        }
        Individual fittest = tournamentPopulation.individuals[0];
        for(int i = 0; i < tournamentPopulation.individuals.size(); i++){
            if(tournamentPopulation.individuals[i].fitness > fittest.fitness){
                fittest = tournamentPopulation.individuals[i];
            }
        }
        return fittest;
    }
    void crossover(Individual &parent1, Individual &parent2, Individual &child){
        int crossoverPoint = rand()%parent1.chromosome.size();
        for(int i = 0; i < crossoverPoint; i++){
            child.chromosome[i] = parent1.chromosome[i];
        }
        for(int i = crossoverPoint; i < parent1.chromosome.size(); i++){
            child.chromosome[i] = parent2.chromosome[i];
        }
    }
    void mutate(Individual &individual){
        for(int i = 0; i < individual.chromosome.size(); i++){
            if((double)rand()/RAND_MAX < mutationRate){
                individual.chromosome[i] = 1 - individual.chromosome[i];
            }
        }
    }
    Individual getFittest(Population &population){
        Individual fittest = population.individuals[0];
        for(int i = 0; i < population.individuals.size(); i++){
            if(population.individuals[i].fitness > fittest.fitness){
                fittest = population.individuals[i];
            }
        }
        return fittest;
    }
    Population evolvePopulation(Population &population){
        Population newPopulation(0, population.individuals[0].chromosome.size());
        if(elitism){
            Individual fittest = getFittest(population);
            newPopulation.individuals.push_back(fittest);
        }
        while(newPopulation.individuals.size() < population.individuals.size()){
            Individual parent1 = tournamentSelection(population);
            Individual parent2 = tournamentSelection(population);
            Individual child(0);
            crossover(parent1, parent2, child);
            mutate(child);
            newPopulation.individuals.push_back(child);
        }
        return newPopulation;
    }
};

int main(){
    srand(time(NULL));
    int populationSize = 100;
    int chromosomeLength = 50;
    int numGenerations= 200;
    double mutationRate = 0.01;
    int tournamentSize = 5;
    bool elitism = true;
    Population population(populationSize, chromosomeLength);
    GeneticAlgorithm ga(mutationRate, tournamentSize, elitism);
    for(int i = 0; i < numGenerations; i++){
        ga.evaluatePopulation(population);
        cout << "Generation " << i << ": Fittest individual has fitness " << ga.getFittest(population).fitness << endl;
        population = ga.evolvePopulation(population);
    }
    cout << "Solution found:" << endl;
    Individual fittest = ga.getFittest(population);
    for(int i = 0; i < fittest.chromosome.size(); i++){
        cout << fittest.chromosome[i];
    }
    cout << endl;
    return 0;
}

Для интереса я попробовал выведать у бота как он работает и как можно реализовать у себя такого же. К сожалению, бот отказался рассказывать детали, а вместо этого выдал код для подключения к API OpenAI.

Hidden text
import openai
openai.api_key = "YOUR_API_KEY"

def generate_answer(prompt):
    response = openai.Completion.create(
        engine="text-davinci-002",
        prompt=prompt,
        max_tokens=1024,
        n=1,
        stop=None,
        temperature=0.5,
    )

    answer = response.choices[0].text.strip()
    return answer

Немного пообщавшись с ним мне все таки удалось узнать у него код для открытой реализации чат-бота основанной на алгоритме GPT-2. Ее выпустила та же OpenAI и этот код находится в открытом доступе. Немного позже я узнал что есть и более продвинутые реализации, например, на основе LLaMA, но разумеется все они будут значительно хуже того, на что способен ChatGPT.

Попробуем поднять планку еще выше и реализовать что-то более значительное, чего я вообще никогда не делал.

Дай реализацию алгоритма на Python в котором на изображении будет подсчитываться количество людей

Hidden text
import cv2

# загрузка изображения
image = cv2.imread("image.jpg")

# загрузка модели YOLO
net = cv2.dnn.readNetFromDarknet("yolov3.cfg", "yolov3.weights")

# получение имен слоев модели
layer_names = net.getLayerNames()
output_layers = [layer_names[i[0] - 1] for i in net.getUnconnectedOutLayers()]

# задание цветов для каждого класса объектов
colors = [[0, 0, 255], [0, 255, 0], [255, 0, 0]]

# обнаружение объектов на изображении
blob = cv2.dnn.blobFromImage(image, 1/255.0, (416, 416), swapRB=True, crop=False)
net.setInput(blob)
outs = net.forward(output_layers)

# подсчет количества людей
count = 0
for out in outs:
    for detection in out:
        scores = detection[5:]
        class_id = np.argmax(scores)
        confidence = scores[class_id]
        if class_id == 0 and confidence > 0.5:
            count += 1
            center_x = int(detection[0] * image.shape[1])
            center_y = int(detection[1] * image.shape[0])
            w = int(detection[2] * image.shape[1])
            h = int(detection[3] * image.shape[0])
            x = int(center_x - w/2)
            y = int(center_y - h/2)
            cv2.rectangle(image, (x,y), (x+w,y+h), colors[class_id], 2)

# вывод результата
print("Количество людей на изображении: ", count)
cv2.imshow("Detection result", image)
cv2.waitKey(0)

По распечатке видно что код делает именно то, что я и попросил: дает количество людей найденных на изображении. Мне это показалось не наглядным и поэтому я скорректировал задание.

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

Hidden text
import cv2

# Загрузка файлов весов и конфигурации модели YOLOv3
net = cv2.dnn.readNet("yolov3.weights", "yolov3.cfg")

# Загрузка изображения
image = cv2.imread("image.jpg")

# Получение размеров изображения
height, width, _ = image.shape

# Создание списка имен классов
classes = []
with open("coco.names", "r") as f:
    classes = [line.strip() for line in f.readlines()]

# Получение индексов классов "человек"
person_indices = [classes.index("person")]

# Создание входного бинарного блоба для модели YOLOv3
blob = cv2.dnn.blobFromImage(image, 1 / 255.0, (416, 416), swapRB=True, crop=False)

# Запуск прямого прохода через модель для обнаружения объектов
net.setInput(blob)
layer_outputs = net.forward(net.getUnconnectedOutLayersNames())

# Инициализация списка обнаруженных фигур людей
people = []

# Проход по каждому выходному слою модели
for output in layer_outputs:
    # Проход по каждому обнаруженному объекту на выходном слое
    for detection in output:
        # Получение вероятности и индекса класса обнаруженного объекта
        scores = detection[5:]
        class_index = scores.argmax() + 5

        # Проверка, что обнаруженный объект - человек
        if class_index in person_indices:
            # Получение координат ограничивающего прямоугольника
            box = detection[0:4] * np.array([width, height, width, height])
            x_center, y_center, box_width, box_height = box.astype("int")
            x, y = int(x_center - (box_width / 2)), int(y_center - (box_height / 2))

            # Добавление ограничивающего прямоугольника в список людей
            people.append((x, y, int(box_width), int(box_height)))

# Отрисовка ограничивающих прямоугольников на изображении
for (x, y, w, h) in people:
    cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)

# Вывод количества найденных людей на изображении
cv2.putText(image, f"Number of people: {len(people)}", (10, height - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)

# Отображение изображения с ограничивающими прямоугольниками и количеством найденных людей
cv2.imshow("Image", image)
cv2.waitKey(0)

Вот это уже совсем другое дело! Возникла всего лишь одна проблема: программа не нашла на изображении ни одного человека.

Не беда, я сделал еще одну попытку.

Код, который ты мне дал не работает. Дай реализацию основанную на другой библиотеке.

Hidden text
import cv2
import numpy as np
import tensorflow as tf

# Загрузка модели TensorFlow
model = tf.saved_model.load('path/to/saved_model')

# Загрузка изображения
img = cv2.imread('path/to/image')

# Преобразование изображения в массив numpy и нормализация
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img = cv2.resize(img, (300, 300))
img = img.astype('float32')
img = img / 255.0
img = np.expand_dims(img, axis=0)

# Обнаружение объектов на изображении
detections = model(img)

# Извлечение координат и классов обнаруженных объектов
boxes = detections['detection_boxes'][0].numpy()
classes = detections['detection_classes'][0].numpy().astype(np.uint32)
scores = detections['detection_scores'][0].numpy()

# Отображение результатов
for i in range(len(boxes)):
    if classes[i] == 1 and scores[i] > 0.5:
        ymin, xmin, ymax, xmax = boxes[i]
        xmin = int(xmin * img.shape[2])
        xmax = int(xmax * img.shape[2])
        ymin = int(ymin * img.shape[1])
        ymax = int(ymax * img.shape[1])
        cv2.rectangle(img, (xmin, ymin), (xmax, ymax), (0, 255, 0), 2)

# Вывод количества обнаруженных людей на изображении
num_people = np.count_nonzero(classes == 1)
cv2.putText(img, f'People: {num_people}', (10, img.shape[0] - 10), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)

# Отображение изображения с прямоугольниками и количеством людей
cv2.imshow('Image', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

Этот код вообще не запустился. Не отчаиваясь я сделал еще одну попытку.

Этот код тоже не работает. Дай реализацию основанную на третьей библиотеке

Hidden text
import torch
import torchvision
import cv2

# Загружаем предварительно обученную модель Faster R-CNN
model = torchvision.models.detection.fasterrcnn_resnet50_fpn(pretrained=True)

# Переводим модель в режим оценки (evaluation mode)
model.eval()

# Загружаем изображение
image = cv2.imread("Crowd-of-Diverse-People_800x528.jpg")

# Преобразуем изображение в тензор PyTorch
image_tensor = torchvision.transforms.functional.to_tensor(image)

# Добавляем размерность пакета (batch dimension) к тензору изображения
image_tensor = image_tensor.unsqueeze(0)

# Выполняем предсказание
with torch.no_grad():
    outputs = model(image_tensor)

# Получаем предсказанные координаты ограничительных прямоугольников
boxes = outputs[0]["boxes"].numpy()

# Получаем предсказанные оценки уверенности (scores)
scores = outputs[0]["scores"].numpy()

# Отфильтровываем ограничительные прямоугольники с низкими оценками
threshold = 0.5
boxes = boxes[scores >= threshold]

# Рисуем ограничительные прямоугольники на изображении
for box in boxes:
    x1, y1, x2, y2 = box.astype(int)
    cv2.rectangle(image, (x1, y1), (x2, y2), (0, 255, 0), 2)

# Вывод количества обнаруженных людей на изображении
num_people = len(boxes)
cv2.putText(image, f'People: {num_people}', (10, image.shape[0] - 10), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)

# Отображение изображения с прямоугольниками и количеством людей
cv2.imshow('Image', image)
cv2.waitKey(0)
cv2.destroyAllWindows()

Этот код оказался работоспособным. Он успешно обвел найденных на изображении людей.

На последнем изображении алгоритм перестарался и нашел немного больше людей чем там было. Но вряд ли вы будете спорить с тем, что результат весьма неплох для получаса работы человека, который вообще не углублялся в детали работы программы. Так что можно констатировать тот факт, что порог входа в область машинного обучения значительно снизился. Этим может заниматься практически любой программист который способен внятно формулировать задания на обычном человеческом языке. И это стало возможно также благодаря нейросетям.

Итог

Можно уверенно сказать что нейросети способны принести большую пользу для бизнеса. Другое дело что этот потенциал мало кто использует. В основном его используют компании, которые уперлись в пределы своего развития, и поэтому без нейросетей уже не видят продвижения вперед. Но так поступают далеко не все. Некоторые достигнув предела роста находятся там, довольствуясь тем малым, которого удалось достичь. Надеюсь что мои читатели не такие. Надеюсь что мои читатели захотят воспользоваться любой возможностью, которая перед ними откроется, и с такими читателями будет интересно поговорить в комментариях.

Я понимаю что основная аудитория хабра - это программисты. Скорее всего у вас будут более интересные идеи, чем у меня. Я не имею ввиду идеи генерации запросов к REST  интерфейсу. Я имею ввиду запросы по которым можно генерировать интересный код с применением нейронных сетей. Вот, например, я думаю о том, как можно обрабатывать видеоизображения. Проблема в том, что мне не получается придумать задачу для решения которой это было бы необходимо. Надеюсь вы понимаете проблему с которой я столкнулся. Дефицит не в количестве подходов к решению задач, дефицит в количестве идей, которые действительно стоит решать. И чтобы восполнить этот дефицит требуются люди с особым складом ума. Поэтому надеюсь вы понимаете что данная статья в первую очередь направлена к представителям бизнеса, которые именно то и делают, что стремятся извлечь максимально возможную прибыль. И я прошу вас это понять.

Всем известно что есть два основных направления образования - это гуманитарное и техническое. Первое учит отвечать на вопрос что надо делать, а второе как этого можно достичь. Разумеется, все не так просто, и технари со временем могут стать гуманитариями и наоборот, но здесь важно одно: есть цель, и есть средство ее достижения. В этой статье я хотел показать что со средствами достижения в общем-то стало неплохо. Какие цели мы должны достигать? Вот это именно то, что хотелось бы узнать. Я понимаю что и здесь нет никаких проблем, есть шаблонные желания, типа достижения мира во всем мире, и чтобы всем в результате стало хорошо. Но судя по происходящему в мире к этой цели стремится слишком мало людей. А впрочем, я похоже замечтался. У меня слишком глобальные мысли. Поэтому было бы интересно выслушать людей, которые реально заняты делом и которым нужны люди способные решать действительно сложные задачи. Надеюсь что это именно вы.

Разумеется, некоторые цели очень сложно достичь. Согласен. Давайте не будем говорить о невозможном. Давайте говорить о возможном, а я надеюсь что смог показать что на данный момент возможным стало очень многое. Стало возможным то, о чем даже год назад мы не могли и мечтать. Вопрос остался всего лишь в ресурсах. Мечтать мы можем о многом, а вот потратить свои средства на достижение мечты способен далеко не каждый, и это реальная проблема. Что ж, с этим приходится мириться. Увы…

А впрочем, что я говорю? Есть люди, которые реально тратят существенные средства на ту мечту, которую в данный момент достичь почти невозможно, и эти люди оказались способны значительно продвинуться на этом направлении. Именно благодаря стараниям этих людей люди продолжают выходить в космос. Именно благодаря стараниям этих людей появились самоуправляемые машины. Именно благодаря стараниям этих людей появился такой развитый искусственный интеллект как ChatGPT. Мне кажется что мы должны быть благодарны этим людям. Должны быть благодарны им в том, что они захотели достичь невозможного, и именно поэтому они особенно успешны. Мне кажется что на таких людей и стоит равняться.

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


  1. AnyaPetrova
    00.00.0000 00:00

    Интересно. Но у меня, как у новичка в программировании, вызывает недоумение один момент. Я много сил трачу на то, чтобы разобраться с каждой строчкой кода и вроде бы добиваюсь успеха. А тут нужно просто правильно сформулировать вопрос ChatGPT и все готово. Как глубоко я должна освоить эту тему, чтобы войти в профессию?