добавили комменты к строкам, возможно придется переписать бд🤩🤩🤩

This commit is contained in:
an.lazarev 2024-11-05 21:57:32 +04:00
parent cf0ff194d2
commit 7022fdb50b
2 changed files with 82 additions and 78 deletions

View File

@ -1,12 +1,12 @@
import gc import gc
import logging import logging
import time import time
from datetime import datetime from datetime import datetime, timedelta
from pprint import pprint
import mariadb import mariadb
import serial.tools.list_ports import serial.tools.list_ports
from PyWeather.weather.stations.davis import VantagePro #from PyWeather.weather.stations.davis import VantagePro
from prediction import run_prediction_module from prediction import run_prediction_module
logging.basicConfig(filename="Stations.log", logging.basicConfig(filename="Stations.log",
@ -54,28 +54,27 @@ def write_data(device, station, send=True):
def get_previous_values(cursor): def get_previous_values(cursor):
cursor.execute("SELECT SunRise, SunSet, WindDir FROM weather_data ORDER BY DateStamp DESC LIMIT 1") cursor.execute("SELECT SunRise, SunSet, WindDir, DateStamp FROM weather_data ORDER BY DateStamp DESC LIMIT 1")
result = cursor.fetchone() result = cursor.fetchone()
if result is None: if result is None:
return None, None, None return None, None, None, None
sun_rise, sun_set, wind_dir = result sun_rise, sun_set, wind_dir, datestamp = result
return sun_rise, sun_set, wind_dir return sun_rise, sun_set, wind_dir, datestamp
def save_prediction_to_db(predictions): def save_prediction_to_db(predictions):
try: try:
current_timestamp = datetime.now()
sun_rise, sun_set, wind_dir = get_previous_values(cursor) sun_rise, sun_set, wind_dir, datestamp = get_previous_values(cursor)
fields = ['DateStamp', 'SunRise', 'SunSet', 'WindDir'] + list(predictions.keys()) fields = ['DateStamp', 'SunRise', 'SunSet', 'WindDir'] + list(predictions.keys())
placeholders = ', '.join(['%s'] * len(fields)) placeholders = ', '.join(['%s'] * len(fields))
field_names = ', '.join(fields) field_names = ', '.join(fields)
values = [current_timestamp, sun_rise, sun_set, wind_dir] + list(predictions.values()) values = [datestamp + timedelta(minutes = 1), sun_rise, sun_set, wind_dir] + list(predictions.values())
pprint(dict(zip(fields, values)))
sql = f"INSERT INTO weather_data ({field_names}) VALUES ({placeholders})" sql = f"INSERT INTO weather_data ({field_names}) VALUES ({placeholders})"
# cursor.execute(sql, values) # cursor.execute(sql, values)
# conn.commit() # conn.commit()
@ -97,8 +96,8 @@ try:
except mariadb.Error as e: except mariadb.Error as e:
logger.error('DB_ERR: ' + str(e)) logger.error('DB_ERR: ' + str(e))
raise e raise e
while True:
try: try:
ports = serial.tools.list_ports.comports() ports = serial.tools.list_ports.comports()
available_ports = {} available_ports = {}
@ -107,18 +106,21 @@ try:
available_ports[port.name] = port.vid available_ports[port.name] = port.vid
devices = [VantagePro(port) for port in available_ports.keys()] devices = [VantagePro(port) for port in available_ports.keys()]
while True: while True:
for i in range(1): for i in range(1):
if len(devices) != 0: if len(devices) != 0:
logger.info(devices) logger.info(devices)
# write_data(devices[i], 'st' + str(available_ports[list(available_ports.keys())[i]]), True) # write_data(devices[i], 'st' + str(available_ports[list(available_ports.keys())[i]]), True)
else: else:
raise Exception("Can't connect to device") raise Exception('Can`t connect to device')
time.sleep(1) time.sleep(60)
except Exception as e: except Exception as e:
logger.error('Device_error: ' + str(e)) logger.error('Device_error' + str(e))
predictions = run_prediction_module() predictions = run_prediction_module()
logger.info(predictions) #logger.info(predictions)
if predictions is not None: if predictions is not None:
save_prediction_to_db(predictions) save_prediction_to_db(predictions)
time.sleep(60)
#todo переписать под influx, для линухи приколы сделать

View File

@ -16,86 +16,88 @@ def run_prediction_module():
FROM weather_data FROM weather_data
WHERE DateStamp >= '2024-10-14 21:00:00' - INTERVAL 36 HOUR; WHERE DateStamp >= '2024-10-14 21:00:00' - INTERVAL 36 HOUR;
""" """
df = pd.read_sql(query, engine) df = pd.read_sql(query, engine) # Загружаем данные из SQL-запроса в DataFrame
df['DateStamp'] = pd.to_datetime(df['DateStamp']) df['DateStamp'] = pd.to_datetime(df['DateStamp']) # Преобразуем столбец 'DateStamp' в формат datetime
df.set_index('DateStamp', inplace=True) df.set_index('DateStamp', inplace=True) # Устанавливаем 'DateStamp' как индекс
df.sort_index(inplace=True) df.sort_index(inplace=True) # Сортируем DataFrame по индексу (по дате)
lags = 3 lags = 3 # Задаем количество временных сдвигов (лагов)
shifted_dfs = [df] shifted_dfs = [df] # Создаем список для хранения исходного DataFrame и его лаговых версий
for lag in range(1, lags + 1): for lag in range(1, lags + 1):
shifted_df = df.shift(lag).add_suffix(f'_t-{lag}') shifted_df = df.shift(lag).add_suffix(f'_t-{lag}') # Создаем сдвинутый на lag строк DataFrame
shifted_dfs.append(shifted_df) shifted_dfs.append(shifted_df) # Добавляем его в список
df_with_lags = pd.concat(shifted_dfs, axis=1) df_with_lags = pd.concat(shifted_dfs, axis=1) # Объединяем исходный DataFrame и все лаги по столбцам
df_with_lags.dropna(inplace=True) df_with_lags.dropna(inplace=True) # Удаляем строки с пропущенными значениями
df_with_lags = df_with_lags.copy() df_with_lags = df_with_lags.copy() # Создаем копию DataFrame (для предотвращения предупреждений)
# Преобразуем BarTrend в числовой формат # Преобразуем столбец 'BarTrend' в числовой формат, используя кодировщик категорий
le = LabelEncoder() le = LabelEncoder()
df_with_lags['BarTrend_encoded'] = le.fit_transform(df_with_lags['BarTrend']) df_with_lags['BarTrend_encoded'] = le.fit_transform(df_with_lags['BarTrend'])
# Выбор только числовых данных # Оставляем в DataFrame только числовые столбцы
df_with_lags = df_with_lags.select_dtypes(include=['float64', 'int64']) df_with_lags = df_with_lags.select_dtypes(include=['float64', 'int64'])
# Словари для хранения моделей и MSE # Создаем словари для хранения моделей и значений MSE
models = {} models = {}
mse_scores = {} mse_scores = {}
# Обучение моделей для каждого целевого столбца # Обучаем модели для каждого целевого столбца
for target_column in df.columns: for target_column in df.columns:
if target_column not in df_with_lags.columns: if target_column not in df_with_lags.columns: # Пропускаем, если столбец отсутствует в df_with_lags
continue continue
X = df_with_lags.drop(columns=[target_column]).values X = df_with_lags.drop(columns=[target_column]).values # Признаки - все столбцы, кроме целевого
y = df_with_lags[target_column].values y = df_with_lags[target_column].values # Целевой столбец
# Разделяем данные на обучающую и тестовую выборки без перемешивания (временной ряд)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, shuffle=False) X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, shuffle=False)
model = RandomForestRegressor() model = RandomForestRegressor() # Инициализируем модель случайного леса
model.fit(X_train, y_train) model.fit(X_train, y_train) # Обучаем модель
y_pred = model.predict(X_test) y_pred = model.predict(X_test) # Делаем предсказания на тестовой выборке
mse = mean_squared_error(y_test, y_pred) mse = mean_squared_error(y_test, y_pred) # Вычисляем среднеквадратичную ошибку
mse_scores[target_column] = mse mse_scores[target_column] = mse # Сохраняем MSE для целевого столбца
models[target_column] = model models[target_column] = model # Сохраняем модель для целевого столбца
quality = "хорошая" if mse < 1.0 else "плохая" quality = "хорошая" if mse < 1.0 else "плохая" # Определяем качество модели
print(f"MSE для {target_column}: {mse} ({quality})") print(f"MSE для {target_column}: {mse} ({quality})") # Выводим MSE и качество
# Обучаем модель для BarTrend_encoded отдельно # Обучаем модель для столбца 'BarTrend_encoded' отдельно
X_bartrend = df_with_lags.drop(columns=['BarTrend_encoded']).values X_bartrend = df_with_lags.drop(columns=['BarTrend_encoded']).values # Признаки
y_bartrend = df_with_lags['BarTrend_encoded'].values y_bartrend = df_with_lags['BarTrend_encoded'].values # Целевой столбец 'BarTrend_encoded'
# Разделяем данные на обучающую и тестовую выборки без перемешивания
X_train_bartrend, X_test_bartrend, y_train_bartrend, y_test_bartrend = train_test_split(X_bartrend, y_bartrend, X_train_bartrend, X_test_bartrend, y_train_bartrend, y_test_bartrend = train_test_split(X_bartrend, y_bartrend,
test_size=0.2, test_size=0.2,
shuffle=False) shuffle=False)
model_bartrend = RandomForestRegressor() model_bartrend = RandomForestRegressor() # Инициализируем модель случайного леса
model_bartrend.fit(X_train_bartrend, y_train_bartrend) model_bartrend.fit(X_train_bartrend, y_train_bartrend) # Обучаем модель
y_pred_bartrend = model_bartrend.predict(X_test_bartrend) y_pred_bartrend = model_bartrend.predict(X_test_bartrend) # Предсказания на тестовой выборке для 'BarTrend_encoded'
mse_bartrend = mean_squared_error(y_test_bartrend, y_pred_bartrend) mse_bartrend = mean_squared_error(y_test_bartrend, y_pred_bartrend) # Вычисляем MSE
models['BarTrend_encoded'] = model_bartrend models['BarTrend_encoded'] = model_bartrend # Сохраняем модель для 'BarTrend_encoded'
mse_scores['BarTrend_encoded'] = mse_bartrend mse_scores['BarTrend_encoded'] = mse_bartrend # Сохраняем MSE для 'BarTrend_encoded'
quality_bartrend = "хорошая" if mse_bartrend < 1.0 else "плохая" quality_bartrend = "хорошая" if mse_bartrend < 1.0 else "плохая" # Определяем качество модели для 'BarTrend_encoded'
print(f"MSE для BarTrend: {mse_bartrend} ({quality_bartrend})") print(f"MSE для BarTrend: {mse_bartrend} ({quality_bartrend})") # Выводим MSE и качество
last_data = X[-1].reshape(1, -1) last_data = X[-1].reshape(1, -1) # Берем последнюю строку данных и преобразуем в формат для предсказания
predictions = {} predictions = {} # Создаем словарь для хранения предсказаний
for target_column, model in models.items(): for target_column, model in models.items():
prediction = model.predict(last_data)[0] prediction = model.predict(last_data)[0] # Делаем предсказание для последней строки данных
if target_column == 'BarTrend_encoded': if target_column == 'BarTrend_encoded':
prediction = le.inverse_transform([int(prediction)])[0] prediction = le.inverse_transform([int(prediction)])[0] # Декодируем категориальное значение
predictions['BarTrend'] = prediction predictions['BarTrend'] = prediction # Сохраняем предсказание для 'BarTrend'
print(f"Предсказание для BarTrend: {prediction}") #print(f"Предсказание для BarTrend: {prediction}") # Выводим предсказание
break continue # Продолжаем цикл после предсказания для 'BarTrend_encoded'
predictions[target_column] = prediction predictions[target_column] = prediction # Сохраняем предсказание для остальных столбцов
print(f"Предсказание для {target_column}: {prediction}") #print(f"Предсказание для {target_column}: {prediction}") # Выводим предсказание для столбца
return predictions # Возвращаем словарь с предсказанными значениями и названиями столбцов return predictions # Возвращаем словарь с предсказанными значениями и названиями столбцов