Форум программистов, компьютерный форум, киберфорум
Python: Решение задач
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.95/21: Рейтинг темы: голосов - 21, средняя оценка - 4.95
2 / 2 / 0
Регистрация: 16.06.2021
Сообщений: 9

Кусочно-постоянная функция

29.09.2021, 12:42. Показов 4851. Ответов 8

Студворк — интернет-сервис помощи студентам
Дана кусочно-постоянная функция F: https://www.cyberforum.ru/cgi-bin/latex.cgi?<br />
f(x) = \begin{cases}<br />
    a       , & x < c\\<br />
    b  , & x \geq c<br />
  \end{cases}

Напишите на Python 3 программу, которая принимает на вход массив A пар (x, y) длины n, и возвращает кортеж из трех элементов (a, b, c), соответствующих параметрам функции F, при которых среднеквадратическое отклонение функции от точек из A минимально.
Визуализация решения приветствуется.

Буду благодарен за помощь с решением, спасибо!
1
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
29.09.2021, 12:42
Ответы с готовыми решениями:

Кусочно-ломанная функция
Помогите запрограммировать эту функцию на Питоне и разместить ее в модуле

кусочно-линейная функция изменения температуры
Дана такая кусочно-линейная функция изменения температуры со временем T-температура, t — время, 4 точки температуры задаются произвольно...

Кусочно заданная функция
#include&lt;iostream&gt; #include &lt;iomanip&gt; #include &lt;conio.h&gt; #include&lt;stdio.h&gt; #include&lt;math.h&gt; using namespace std; void...

8
Супер-модератор
Эксперт функциональных языков программированияЭксперт Python
 Аватар для Catstail
38169 / 21104 / 4307
Регистрация: 12.02.2012
Сообщений: 34,695
Записей в блоге: 14
29.09.2021, 19:53
Хорошая задача! Буду думать. Начать, мне кажется, нужно с кластеризации. Разбить исходные данные на два кластера. Действовать можно так: начиная от меньших x к большим и от больших x - к меньшим начать строить 2 кластера, постоянно пересчитывая среднее значение y и уточняя остаточную сумму квадратов.

Добавлено через 54 минуты
Если ступенька точно одна, то можно ограничиться одним кластером. Сортируем пары по X. Берем начальные куски блока данных увеличивающейся длины и считаем среднее по y. Фиксируем последнее резкое изменение среднего.

Сугубо прикидочный вариант:

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
from random import random
 
# Генерация тестовых данных
 
def make_data(a,b,c,sa,sb,n,xmin,xmax):
    r=[]
    for i in range(n):
        # генерируем случайную точку xmax > x > xmin
        x=random()*(xmax-xmin)+xmin
        # генерируем соотв. y
        if x<c:
            y=random()*sa*0.5+a
        else:
            y=random()*sb*0.5+b
        r.append((x,y))
    return r
 
# среднее по кластеру
 
def calc_avg(clast):
    s=sum(map(lambda pair: pair[1],clast))
    avg=s/len(clast)
    return avg
 
# вот данные, соответствующие ступеньке при c=3 a=-1 b=1
# 1000 точек, равномерно разбросанных от -5 до 5 (0.3 - разброс по y)
 
dd=sorted(make_data(-1,1, 3 ,0.3,0.3,1000,-5,5))
 
avg_prev,da_prev=None,None
 
for i in range(10,1000,10):
    clast_left=dd[0:i]
    avg_curr=calc_avg(clast_left)
    if avg_prev is None:
        avg_prev=avg_curr
    else:
        da_curr=abs(avg_curr-avg_prev)
        if da_prev is None:
            da_prev=da_curr
        else:
            if da_curr/da_prev>30: # резкое изменение 
                print(i)
            da_prev=da_curr
            avg_prev=avg_curr
Фиксирует ступеньку в районе 800-й точки (это верно).
2
5515 / 2868 / 571
Регистрация: 07.11.2019
Сообщений: 4,759
29.09.2021, 20:47
Catstail, думаю, что все правильно вы написали.
Но тут скорее всего нужен алгоритм итеративного вычисления среднего, дисперсии двух выборок. Подобный алгоритм был еще в советских инженерных калькуляторах при статистических расчетах.
На первом шаге считаем, что слева у нас одна точка, справа - все остальные. На следующем шаге добавляем к левой части еще одну точку, а справа удаляем точку. На каждом шаге корректируется среднее значение для левой части данных и для правой, тоже самое и с дисперсиями. Дисперсии левой и правых частей складываются для каждого C - это будет целевая функция. Т.е. все считается почти за один проход.
2
2 / 2 / 0
Регистрация: 16.06.2021
Сообщений: 9
30.09.2021, 00:39  [ТС]
Пока это не кажется просто, надо переспать с этими новыми знаниями)
По сути нам просто приближенная по МНК прямая нужна, которая разделит точки, а сама станет той самой С, в правильном направлении мыслю? Но у нас нет классов, что сильно усложняет решение задачи, хотя может и упрощает, это пока что тоже не понял) но весь день я сегодня мыслил именно в таком направлении.
0
5515 / 2868 / 571
Регистрация: 07.11.2019
Сообщений: 4,759
30.09.2021, 03:47
Если использовать nympy, то как-то так:
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import matplotlib.pyplot as plt
import numpy as np
n=5
# исходные данные
y=np.random.uniform(0, 3, size=n)
x=np.random.uniform(-10, 10, size=n)
# сортировака данных по x
idx=np.argsort(x)
x=x[idx]
y=y[idx]
 
a=[]
b=[]
c=[]
r=[]
for i in range(1, n):
    c.append(x[i])
    a.append(np.mean(y[:i]))
    b.append(np.mean(y[i:]))
    r.append(np.std(y[:i])+np.std(y[i:]))
idx=np.argmin(r)
print(a[idx], b[idx], c[idx])
plt.plot(x,y, 'ro')
stepx=np.array([x[0],c[idx],c[idx], x[-1]])
stepy=np.array([a[idx], a[idx],b[idx],b[idx]])
plt.plot(stepx, stepy, 'g-')
Тут, как уже говорил, хорошо бы использовать инкрементальные формулы вычисления среднего и дисперсии..
Миниатюры
Кусочно-постоянная функция  
3
Супер-модератор
Эксперт функциональных языков программированияЭксперт Python
 Аватар для Catstail
38169 / 21104 / 4307
Регистрация: 12.02.2012
Сообщений: 34,695
Записей в блоге: 14
30.09.2021, 06:39
Цитата Сообщение от miracle- Посмотреть сообщение
Но у нас нет классов, что сильно усложняет решение
Во-первых, классы в Питоне, разумеется, есть,

Во-вторых, что ООП может дать в данной задаче? Меня умиляет стремление некоторых программистов использовать ООП "и в хвост и в гриву" - там, где нужно, и там, где не нужно. Типичная задача такого рода - "дан радиус окружности, вычислить ее площадь "через ООП". Зачем тут ООП? Объекты со сложным поведением, обменивающиеся сообщениями? Сложная иерархия объектов?

Сказанное в полной мере можно отнести и к этой задаче.

А вот МНК здесь применять нет особого смысла. Ординаты точек группируются вокруг одной (a) или другой (b) точки на оси OY. Вычисляем среднюю - и все.
0
2 / 2 / 0
Регистрация: 16.06.2021
Сообщений: 9
30.09.2021, 13:17  [ТС]
Цитата Сообщение от u235 Посмотреть сообщение
Если использовать nympy, то как-то так:
Ух ты хорошее и понятное решение. Единственное, что хотелось бы уточнить: почему мы начинаем цикл с единицы и забываем про первый элемент массива(он же нулевой в python)? То есть в "с" мы сразу добавляем первый элемент, а в общей сложности там получается n-1 элементов.

Цитата Сообщение от Catstail Посмотреть сообщение
Во-первых, классы в Питоне, разумеется, есть,
Во-вторых, что ООП может дать в данной задаче? Меня умиляет стремление некоторых программистов использовать ООП "и в хвост и в гриву" - там, где нужно, и там, где не нужно. Типичная задача такого рода - "дан радиус окружности, вычислить ее площадь "через ООП". Зачем тут ООП? Объекты со сложным поведением, обменивающиеся сообщениями? Сложная иерархия объектов?
Мы друг друга не правильно поняли... Для меня, как для начинающего исследователя данных, классы - это именно метки объектов, то есть вектор чисел с отнесением объекта(в нашем случае пара x и y) к какому-то, как вы пишете, кластеру.
ООП совсем не хотел сюда прикручивать и понимал, что задачка решается буквально одним циклом. Я одним не смог, у меня два получалось и считалось как-будто не правильно(на бумаге другие значения немного получались), но мы уже выяснили, благодаря предыдущему ответу, что задачу можно решить используя минимум иерархии.


Спасибо всем за участие, помощь и удачи в решении новых задач!!
0
5515 / 2868 / 571
Регистрация: 07.11.2019
Сообщений: 4,759
30.09.2021, 13:31
miracle-, потому что иначе в левом кластере совсем не будет элементов из-за строгого неравенства.
0
2 / 2 / 0
Регистрация: 16.06.2021
Сообщений: 9
01.10.2021, 12:29  [ТС]
u235, Совсем немного решение не докрутили, поэтому делюсь окончательным вариантом, в надежде, что кому-то пригодится.
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import numpy as np
from sklearn.metrics import mean_squared_error as mse
%matplotlib inline
import matplotlib.pyplot as plt
def solve(A):
    optimal_params = {k: 0 for k in 'abc'}
    best_mse = None
    domain = A[A[:, 0].argsort()]
 
    for i in range(1, len(domain) - 1):
        y_left, y_right = domain[:i, 1], domain[i:, 1]
 
        mean_left, mean_right = np.mean(y_left), np.mean(y_right)
 
        loss = np.mean(np.square(np.concatenate([y_left - mean_left, y_right - mean_right])))
        if (best_mse is None or loss < best_mse):
            best_mse = loss
            optimal_params['a'], optimal_params['b'], optimal_params['c'] = mean_left, mean_right, domain[i, 0]
            
    return optimal_params['a'], optimal_params['b'], optimal_params['c']
 
# для проверки решения
def create_f(a, b, c):
    return lambda x: a if x < c else b
 
def calc_loss(domain, f):
    return mse(domain[:, 1], np.array([f(x) for x in domain[:, 0]]))
 
n=100
# исходные данные
y=np.random.uniform(0, 3, size=n)
x=np.random.uniform(-10, 10, size=n)
# сортировака данных по x
idx=np.argsort(x)
x=x[idx]
y=y[idx]
 
A = np.stack([x, y]).T
 
a=[]
b=[]
c=[]
r=[]
for i in range(1, n):
    c.append(x[i])
    a.append(np.mean(y[:i]))
    b.append(np.mean(y[i:]))
    r.append(np.std(y[:i]) + np.std(y[i:])) # в сумме std для подмножеств y[:i] и y[i:] сладагемые участвуют с разными "коэфициентами": 1/i и 1/(n - i) соответственно, в отличие от mse, где все слагаемые участвуют с 1/n. Минимум суммы std не совпадает с минимумом mse (строго убедиться в этом можно, взяв производные) и, следовательно, не решает задачу.
idx=np.argmin(r)
print(a[idx], b[idx], c[idx])
a, b, c = a[idx], b[idx], c[idx]
calc_loss(A, create_f(a, b, c)) # mse для данных a, b, c
 
a, b, c = solve(A)
calc_loss(A, create_f(a, b, c)) # mse для данных a, b, c
 
plt.plot(x, y, 'ro')
stepx=np.array([x[0], c, c, x[-1]])
stepy=np.array([a, a, b, b])
plt.plot(stepx, stepy, 'g-');
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
01.10.2021, 12:29
Помогаю со студенческими работами здесь

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

Кусочно заданная функция
Доброго времени суток. Как в Maple 17 задать кусочно заданную функцию:

Кусочно-непрерывная функция
Что за не понятный скачек между значениями аргумента 2 и 3? Почему не строит сразу от 2 прямую, как задано по алгоритму? Еще пример, что...

Кусочно ломанная функция
1. Разработать алгоритм нахождения значений заданной кусочно- ломаной функции. 2. На основании алгоритма построить ...

кусочно-заданая функция
Всем привет, не подскажите у меня кусочно-заданая функция x1,x2 =1: 0.01:10; % Задаём три разных интервала по x x1 = -10 : 0.01 :...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
Установка Emscripten SDK (emsdk) и CMake на Windows для сборки C и C++ приложений в WebAssembly (Wasm)
8Observer8 30.01.2026
Чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. Система контроля версиями Git. . .
Подключение Box2D v3 к SDL3 для Android: физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
Загрузка PNG с альфа-каналом на SDL3 для Android: с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
Загрузка PNG с альфа-каналом на SDL3 для Android: с помощью SDL3_image
8Observer8 27.01.2026
Содержание блога SDL3_image - это библиотека для загрузки и работы с изображениями. Эта пошаговая инструкция покажет, как загрузить и вывести на экран смартфона картинку с альфа-каналом, то есть с. . .
Влияние грибов на сукцессию
anaschu 26.01.2026
Бифуркационные изменения массы гриба происходят тогда, когда мы уменьшаем массу компоста в 10 раз, а скорость прироста биомассы уменьшаем в три раза. Скорость прироста биомассы может уменьшаться за. . .
Воспроизведение звукового файла с помощью SDL3_mixer при касании экрана Android
8Observer8 26.01.2026
Содержание блога SDL3_mixer - это библиотека я для воспроизведения аудио. В отличие от инструкции по добавлению текста код по проигрыванию звука уже содержится в шаблоне примера. Нужно только. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru