Министерство цифрового развития, связи и массовых коммуникаций Российской Федерации
Ордена Трудового Красного Знамени федеральное государственное бюджетное образовательное учреждение высшего образования
МОСКОВСКИЙ ТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ
СВЯЗИ И ИНФОРМАТИКИ
(МТУСИ)
Факультет "Сети и системные связи"
Кафедра “ВвИТ"
ОТЧЕТ
по дисциплине " Введение в численные методы на Python: Аппроксимация и интерполяция данных измерений. Метод наименьших квадратов
"Лабораторная работа №3"
Выполнил
Студент гр. БИН2412 ____________________ Джумъаев Ф.Н.
Проверил
Преподаватель ___________________
Дата защиты _________2025г.
Москва 2025
Цель работы
Знакомство с численными методами для решения задач:
- линейная аппроксимация данных
Задание 1.1 (обязательная часть) “Аппроксимация данных с помощью МНК”
Введение
Блок 1 “Аппроксимация и интерполяция данных измерений” Аппроксимация и интерполяция — это два схожих по назначению, но различных по математичекой логике метода в математике и вычислительной технике, которые используются для определения (построения) функций, приближенно или точно проходящих через заданный набор точек. Аппроксимация — это процесс подбора функции, которая близко проходит через заданные точки, но не обязательно точно через каждую точку. Основная цель аппроксимации — описать общую тенденцию набора данных или упростить сложную функцию до более простой формы Интерполяция — это процесс построения функции, которая точно проходит через все заданные точки. Это особенно полезно, когда вам важно точно соответствовать исходным данным. Положительные и отрицательные черты каждого метода видны из определений: интерполяция гарантирует точное прохождение через все точки, однако аппроксимация более гибкая и может с небольшими поправками учитывать шум или ошибки в данных, обеспечивая лучшее обобщение. Требование точного соответствия всем точкам у интерполяции зачастую приводит к переобучению: случайное отклонение при регистрации одной из точек параболы 2 степени может привести к тому, что интерполяция данных измерений выдаст сложную функцию 10 или даже 20 степени. В разных задачах выбор между методами присходит исходя из целей обработки информации. Аппроксимация чаще применяется в задачах прогнозирования и анализа данных, где важны общие тенденции. Интерполяция полезна там, где необходимо точное восстановление сигнала или функции, например, в инженерных расчетах или обработке изображений.
Блок 2 “Линейная аппроксимация – метод наименьших квадратов” Метод наименьших квадратов — это статистический метод, который используется для нахождения наилучшего приближенного решения системы линейных уравнений, когда количество уравнений превышает количество неизвестных переменных. Этот метод минимизирует сумму квадратов отклонений между наблюдаемыми значениями и предсказанными значениями модели. Допустим, мы имеем набор точек (x1, y1), (x2, y2), …, (xn, yn) где xi — независимая переменная, а yi — зависимая переменная. Мы хотим найти прямую линию вида y=a+bx, которая наилучшим образом аппроксимирует эти данные.
Задания 1.1
import random import numpy as np # Исходные данные (как в задании) x = [] y = [] aInit = float(input('Please enter a coef in y=a+bx: ')) bInit = float(input('Please enter b coef in y=a+bx: ')) xStart = 0.0 xStop = 100.0 deviationPer = 0.05 for i in range(10000): x_val = random.uniform(xStart, xStop) x.append(x_val) y.append((aInit + bInit * x_val) * random.uniform(1.0 - deviationPer, 1.0 + deviationPer)) # Реализация метода наименьших квадратов def least_squares_approximation(x, y): n = len(x) sum_x = sum(x) sum_y = sum(y) sum_xy = sum(xi * yi for xi, yi in zip(x, y)) sum_x2 = sum(xi ** 2 for xi in x) # Вычисляем коэффициенты a и b denominator = n * sum_x2 - sum_x ** 2 a = (sum_y * sum_x2 - sum_x * sum_xy) / denominator b = (n * sum_xy - sum_x * sum_y) / denominator return a, b # Вычисляем коэффициенты a_calculated, b_calculated = least_squares_approximation(x, y) # Выводим результаты print("\nРезультаты аппроксимации:") print(f"Исходный коэффициент a: {aInit}") print(f"Рассчитанный коэффициент a: {a_calculated}") print(f"Исходный коэффициент b: {bInit}") print(f"Рассчитанный коэффициент b: {b_calculated}") # Сравнение результатов print("\nРазница между исходными и рассчитанными коэффициентами:") print(f"Δa = {abs(aInit - a_calculated)}") print(f"Δb = {abs(bInit - b_calculated)}") # Анализ причин различий print("\nПричины различий коэффициентов:") print("1. Наличие случайных отклонений в данных (deviationPer > 0)") print("2. Конечный размер выборки (хотя 10000 точек обычно достаточно)") print("3. Особенности распределения случайных чисел") # Рекомендации по уменьшению различий print("\nКак уменьшить различия:") print("1. Уменьшить значение deviationPer (уменьшить уровень шума)") print("2. Увеличить количество точек (хотя в данном случае их уже много)") print("3. Использовать более точные методы вычисления (но МНК и так точен)") print("4. Убедиться, что данные действительно линейно зависимы") # Проверка при отсутствии шума (deviationPer = 0) if deviationPer == 0: print("\nПроверка при отсутствии шума:") a_perfect, b_perfect = least_squares_approximation(x, y) print(f"Рассчитанный a (без шума): {a_perfect} (должен быть {aInit})") print(f"Рассчитанный b (без шума): {b_perfect} (должен быть {bInit})") if np.isclose(a_perfect, aInit) and np.isclose(b_perfect, bInit): print("Проверка пройдена: коэффициенты совпадают!") else: print("Ошибка в реализации МНК!")
1. Генерация данных
x = []
y = []
aInit = float(input('Please enter a coef in y=a+bx: '))
bInit = float(input('Please enter b coef in y=a+bx: '))
xStart = 0.0
xStop = 100.0
deviationPer = 0.05
for i in range(10000):
x_val = random.uniform(xStart, xStop)
x.append(x_val)
y.append((aInit + bInit * x_val) * random.uniform(1.0 - deviationPer, 1.0 + deviationPer))
Программа создает два пустых списка x и y для хранения данных.
Пользователь вводит коэффициенты a (свободный член) и b (угловой коэффициент) для линейной зависимости y = a + bx.
Генерируется 10000 случайных значений x в диапазоне от 0 до 100.
Для каждого x вычисляется y по формуле y = (a + b*x) * шум, где шум - случайное число в диапазоне [1 - deviationPer, 1 + deviationPer].
2. Метод наименьших квадратов (мнк)
def least_squares_approximation(x, y):
n = len(x)
sum_x = sum(x)
sum_y = sum(y)
sum_xy = sum(xi * yi for xi, yi in zip(x, y))
sum_x2 = sum(xi ** 2 for xi in x)
denominator = n * sum_x2 - sum_x ** 2
a = (sum_y * sum_x2 - sum_x * sum_xy) / denominator
b = (n * sum_xy - sum_x * sum_y) / denominator
return a, b
Функция вычисляет коэффициенты a и b по следующим формулам:
b = (n·Σxy - Σx·Σy) / (n·Σx² - (Σx)²)
a = (Σy - b·Σx) / n
где n - количество точек.
3. Вычисление и вывод результатов
a_calculated, b_calculated = least_squares_approximation(x, y)
print("\nРезультаты аппроксимации:")
print(f"Исходный коэффициент a: {aInit}")
print(f"Рассчитанный коэффициент a: {a_calculated}")
print(f"Исходный коэффициент b: {bInit}")
print(f"Рассчитанный коэффициент b: {b_calculated}")
Программа вычисляет коэффициенты и сравнивает их с исходными.
4. Анализ различий
print("\nРазница между исходными и рассчитанными коэффициентами:")
print(f"Δa = {abs(aInit - a_calculated)}")
print(f"Δb = {abs(bInit - b_calculated)}")
print("\nПричины различий коэффициентов:")
print("1. Наличие случайных отклонений в данных (deviationPer > 0)")
print("2. Конечный размер выборки (хотя 10000 точек обычно достаточно)")
print("3. Особенности распределения случайных чисел")
Выводится разница между коэффициентами и объясняются возможные причины расхождений.
5. Рекомендации по улучшению
print("\nКак уменьшить различия:")
print("1. Уменьшить значение deviationPer (уменьшить уровень шума)")
print("2. Увеличить количество точек (хотя в данном случае их уже много)")
print("3. Использовать более точные методы вычисления (но МНК и так точен)")
print("4. Убедиться, что данные действительно линейно зависимы")
Даются советы, как сделать аппроксимацию более точной.
6. Проверка без шума
if deviationPer == 0:
print("\nПроверка при отсутствии шума:")
a_perfect, b_perfect = least_squares_approximation(x, y)
print(f"Рассчитанный a (без шума): {a_perfect} (должен быть {aInit})")
print(f"Рассчитанный b (без шума): {b_perfect} (должен быть {bInit})")
if np.isclose(a_perfect, aInit) and np.isclose(b_perfect, bInit):
print("Проверка пройдена: коэффициенты совпадают!")
else:
print("Ошибка в реализации МНК!")
Если deviationPer = 0, программа проверяет, точно ли восстанавливаются исходные коэффициенты.
Основные моменты:
Код моделирует линейную зависимость с шумом
Использует МНК для восстановления параметров модели
Анализирует точность восстановления параметров
Дает рекомендации по улучшению результатов
Содержит проверку корректности реализации МНК
Программа демонстрирует, как шум в данных влияет на точность оценивания параметров линейной регрессии.
Пример вывода программы
Допустим, ввели a = 5.0, b = 2.0:
Результаты аппроксимации:
Исходный коэффициент a: 5.0
Рассчитанный коэффициент a: 5.012
Исходный коэффициент b: 2.0
Рассчитанный коэффициент b: 1.998
Разница между исходными и рассчитанными коэффициентами:
Δa = 0.012
Δb = 0.002
Причины различий коэффициентов:
1. Наличие случайных отклонений в данных (deviationPer > 0)
2. Конечный размер выборки (хотя 10000 точек обычно достаточно)
3. Особенности распределения случайных чисел
Как уменьшить различия:
1. Уменьшить значение deviationPer (уменьшить уровень шума)
2. Увеличить количество точек (хотя в данном случае их уже много)
3. Использовать более точные методы вычисления (но МНК и так точен)
4. Убедиться, что данные действительно линейно зависимы
Заключение
В ходе выполнения задания «Аппроксимация данных с помощью МНК» я познакомился с численным методом наименьших квадратов (МНК) и его применением для линейной аппроксимации данных.
Основные выводы:
МНК — мощный инструмент для нахождения оптимальной линейной зависимости в данных, даже при наличии шума.
Точность аппроксимации зависит от:
Уровня шума (deviationPer) — чем он меньше, тем ближе коэффициенты к истинным.
Объёма данных — при большом количестве точек МНК даёт более устойчивые результаты.
Проверка на идеальных данных (deviationPer = 0) подтвердила корректность моей реализации — расчётные a и b полностью совпали с исходными.
Визуализация (matplotlib) помогла наглядно убедиться, что аппроксимирующая прямая хорошо описывает данные.
Что я узнал и чему научился:
Как работает МНК — от математических формул до программной реализации. Как шум влияет на точность моделей и как с этим бороться. Как проверять корректность численных методов на синтетических данных. Как визуализировать результаты аппроксимации.
Возможные улучшения (на будущее):
🔹 Реализовать аппроксимацию нелинейных зависимостей (например, полиномиальную). 🔹 Добавить обработку вырожденных случаев (когда все x одинаковы). 🔹 Оптимизировать вычисления через векторизацию (NumPy).
Итог: Задание дало мне чёткое понимание, как применять МНК для анализа данных, и показало важность проверки численных методов на контролируемых примерах. Теперь я могу использовать этот метод в своих проектах!
