Разработка AI-системы для мониторинга животноводства
Крупные животноводческие комплексы — 500+ голов КРС или 10 000+ свиней — не позволяют ветеринару ежедневно осматривать каждое животное. Системы IoT-мониторинга с AI анализируют поведенческие датчики, видео, данные кормления и решают три задачи: ранняя детекция болезней, охота/отёл, оптимизация кормления.
Сенсорная инфраструктура
Типовые датчики на животном:
sensor_types = {
'ear_tag_accelerometer': {
'measures': ['activity_count', 'rumination_time', 'lying_time'],
'vendors': ['SCR (Merck Animal Health)', 'Allflex SenseHub', 'Moocall'],
'frequency': '2-min aggregates'
},
'rumen_bolus': {
'measures': ['rumen_pH', 'rumen_temperature', 'rumen_motility'],
'vendors': ['SmaXtec', 'Medria'],
'frequency': '10-min readings'
},
'milk_meter': {
'measures': ['yield_kg', 'conductivity', 'flow_rate', 'milk_temperature'],
'vendors': ['DeLaval ALPRO', 'Lely T4C'],
'frequency': 'per milking'
},
'weigh_scale': {
'measures': ['body_weight_kg'],
'frequency': 'daily at feeding station'
}
}
Детекция охоты (Estrus Detection)
Алгоритм по активности и руминации:
import pandas as pd
import numpy as np
from scipy.signal import find_peaks
def detect_estrus(animal_id: str, sensor_data: pd.DataFrame,
baseline_days: int = 21) -> dict:
"""
Охота у КРС: резкий рост активности + снижение руминации
Цикл ~21 день — паттерн периодический
"""
recent = sensor_data[sensor_data['animal_id'] == animal_id].tail(baseline_days * 24)
# Нормировка по индивидуальному baseline
activity_baseline = recent['activity_count'].quantile(0.5)
rumination_baseline = recent['rumination_time'].quantile(0.5)
current_24h = sensor_data[
sensor_data['animal_id'] == animal_id
].tail(12) # последние 2 часа (12 × 10-мин блоков)
activity_ratio = current_24h['activity_count'].mean() / (activity_baseline + 1e-9)
rumination_ratio = current_24h['rumination_time'].mean() / (rumination_baseline + 1e-9)
# Охота: активность выше нормы в 2+ раза, руминация снижена
estrus_score = activity_ratio * (2 - rumination_ratio)
# Дополнительно: проверяем повторение 21 день назад
prev_cycle_score = check_previous_cycle(animal_id, sensor_data, days_back=21)
return {
'animal_id': animal_id,
'estrus_score': float(estrus_score),
'estrus_detected': estrus_score > 2.5,
'confidence': 'high' if prev_cycle_score > 2.0 else 'medium',
'recommended_action': 'insemination_window_12-18h' if estrus_score > 2.5 else None
}
Ранняя детекция мастита
Электропроводность молока — главный сигнал:
def mastitis_risk_score(milking_data: pd.DataFrame, animal_id: str) -> float:
"""
Мастит → воспаление → рост ионов Na+, Cl- → рост электропроводности
Сравниваем четверти вымени между собой и с историей
"""
today_milking = milking_data[
(milking_data['animal_id'] == animal_id) &
(milking_data['date'] == milking_data['date'].max())
]
if today_milking.empty:
return 0.0
quarters = ['LF', 'RF', 'LR', 'RR'] # левая передняя, правая передняя, etc.
conductivities = {q: today_milking[f'conductivity_{q}'].mean()
for q in quarters if f'conductivity_{q}' in today_milking.columns}
if len(conductivities) < 2:
return 0.0
mean_cond = np.mean(list(conductivities.values()))
max_deviation = max(abs(v - mean_cond) for v in conductivities.values())
# Порог: >0.5 мСм/см отклонение от среднего = подозрение
relative_deviation = max_deviation / (mean_cond + 1e-9)
# Также: снижение удоя на четверти
yield_deviation = check_yield_drop(animal_id, milking_data, today_milking)
risk_score = 0.6 * (relative_deviation / 0.1) + 0.4 * yield_deviation
return min(1.0, risk_score)
Дополнительные признаки мастита:
- Повышение температуры молока в квартете (+0.5°C)
- Флокуляция — изменение flow rate паттерна
- Снижение общего удоя при сохранении аппетита
- Изменение поведения на доильной установке (время подключения)
Мониторинг здоровья по руминации
Ацидоз рубца (SARA) — снижение pH:
def detect_sara_risk(rumen_bolus_data: pd.DataFrame, animal_id: str) -> dict:
"""
SARA (Sub-Acute Ruminal Acidosis): pH < 5.8 более 3 часов в сутки
Данные от rumen bolus SmaXtec обновляются каждые 10 минут
"""
today_data = rumen_bolus_data[
(rumen_bolus_data['animal_id'] == animal_id) &
(rumen_bolus_data['date'] == pd.Timestamp.today().date())
]
low_ph_minutes = len(today_data[today_data['rumen_pH'] < 5.8]) * 10
# Снижение руминации + низкий pH = SARA
avg_ph = today_data['rumen_pH'].mean() if not today_data.empty else 6.5
rumination_today = today_data['rumen_motility'].mean() if not today_data.empty else 1.0
sara_risk = 'high' if low_ph_minutes > 180 else (
'medium' if low_ph_minutes > 60 else 'low'
)
return {
'animal_id': animal_id,
'low_ph_hours': round(low_ph_minutes / 60, 1),
'avg_ph': round(avg_ph, 2),
'sara_risk': sara_risk,
'action': 'adjust_roughage_ratio' if sara_risk == 'high' else None
}
Групповой анализ и оптимизация кормления
Автоматическое формирование производственных групп:
from sklearn.cluster import KMeans
def form_feeding_groups(herd_data: pd.DataFrame, n_groups: int = 4) -> dict:
"""
Группировка КРС для точного кормления (TMR-рационы)
Признаки: ДИМ (дней в молоке), удой, BCS (упитанность), вес
"""
features = ['days_in_milk', 'milk_yield_7d_avg', 'body_condition_score', 'body_weight']
X = herd_data[features].dropna()
kmeans = KMeans(n_clusters=n_groups, random_state=42, n_init=10)
herd_data.loc[X.index, 'feeding_group'] = kmeans.fit_predict(X)
group_recommendations = {}
for group_id in range(n_groups):
group = herd_data[herd_data['feeding_group'] == group_id]
group_recommendations[group_id] = {
'n_animals': len(group),
'avg_days_in_milk': group['days_in_milk'].mean(),
'target_energy_NEL': calculate_nel_requirement(group),
'crude_protein_pct': calculate_cp_requirement(group)
}
return group_recommendations
Dashboard и алерты: Система выдаёт ежедневный список приоритетных животных для осмотра: топ-10 по composite risk score (мастит + болезнь + охота). Интеграция с программами управления стадом: DairyComp 305, Herd Navigator, SAP Animal Management.
Сроки: Estrus + мастит детекция + базовый дашборд — 4-5 недель. SARA мониторинг, групповое кормление, предиктивные модели заболеваний, интеграция с DairyComp — 2-3 месяца.







