c#通过Pythonnet调用Python编写的预测模型,部署到docker中

1.项目背景

在 .NET 6 项目中嵌套 Python 环境,可以使用 Pythonnet 来调用 Python 编写的预测模型,实现冬季供暖对室内温度的预测功能。这种整合利用了 .NET 的性能和 Python 在数据科学和机器学习方面的强大功能。以下是实现这一功能的总结:

2.已从机器学习导出模型(xgboost_model_all.pkl)和标准化器(scaler.pkl),后续单独讲解预测模型生成

3.Net6项目Pythonnet 用法

 string rootPath = AppDomain.CurrentDomain.BaseDirectory + "python-3.12.3";
复制代码
 #region Python 环境初始化
 /// <summary>
 /// Python 环境初始化
 /// </summary>
 private void PythonInit()
 {
     string pythonDllPath = string.Empty;
     if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
     {
         pythonDllPath = "/usr/local/lib/libpython3.12.so.1.0"; // 设置为Linux上的Python库路径
     }
     if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
     {
         pythonDllPath = $"{rootPath}\\python312.dll";

     }
     modelPath = $"{rootPath}/xgboost_model_all.pkl";
     scalerPath = $"{rootPath}/scaler.pkl";
     Python.Runtime.Runtime.PythonDLL = pythonDllPath;
     PythonEngine.Initialize();
     PythonEngine.BeginAllowThreads();
     using (Py.GIL())
     {
         dynamic joblib = Py.Import("joblib"); // 导入joblib
         dynamic sklearn = Py.Import("sklearn");
         dynamic xgboost = Py.Import("xgboost");
         //np = Py.Import("numpy");
         pandas = Py.Import("pandas");
         linerModel = joblib.load(modelPath);
         standardScaler = joblib.load(scalerPath); // 加载保存的标准化器对象
     }
 }
 #endregion
复制代码

c# 调用使用预测模型方法

复制代码
/// <summary>
/// 预测温度
/// </summary>
/// <param name="preTempModel">参数</param>
/// <param name="weatherTemp">天气温度</param>
/// <returns></returns>
public async Task<List<TempLog>> GetPredict(PreTempModel? preTempModel, double weatherTemp)
{
    List<TempLog> tempLogList = new List<TempLog>();
    if (preTempModel == null)
        return tempLogList;
    try
    {
        var floorHouseDetails = await _basicDataService.GetFloorHouseDetails(preTempModel.CommunityId, preTempModel.BuildingNo);
        // 准备批量预测的数据
        List<double[]> dataBatch = new List<double[]>();
        // 定义输入数据
        for (int i = 0; i < floorHouseDetails.Count; i++)
        {
            var item = floorHouseDetails[i];
            var apartmentType = (ApartmentTypeEnum)Enum.Parse(typeof(ApartmentTypeEnum), item.HouseType);
            double[] dataPoint = new double[]
            {
                    item.FloorNum, preTempModel.InWaterTemp, preTempModel.OutWaterTemp, weatherTemp, (int)apartmentType
            };
            dataBatch.Add(dataPoint);
        }

        lock (_lock)
        {
            using (Py.GIL())
            {
                dynamic dataBatchArray = np.array(dataBatch.ToArray());
                // 标准化数据
                dynamic X_scaled = standardScaler.transform(dataBatchArray);
                var preResulTArrays = linerModel.predict(X_scaled);
                var length = preResulTArrays.shape[0].As<int>();

                int j = 0;
                foreach (var x in preResulTArrays)
                {
                    double preTemperature = double.Parse(x.ToString());
                    tempLogList.Add(new TempLog()
                    {
                        Id = floorHouseDetails[j].Id,
                        CommunityId = floorHouseDetails[j].CommunityId,
                        BuildingNo = floorHouseDetails[j].BuildingNo,
                        UnitNum = floorHouseDetails[j].UnitNum,
                        FloorNum = floorHouseDetails[j].FloorNum,
                        RoomNumber = floorHouseDetails[j].RoomNumber,
                        Date = preTempModel.Date,
                        Hour = preTempModel.Hour,
                        HouseType = floorHouseDetails[j].HouseType,
                        RealTemperature = 0, // 真实温度,这里需要根据具体情况赋值
                        Temperature = preTemperature, // 预测温度
                    });
                    j++;
                }
            }
        }
    }
    catch (Exception ex)
    {
        LogHelper.LogError($"预测温度异常:", ex);
    }

    return tempLogList;
}
复制代码

 

4.项目发布后的目录结构

 

python-3.12.3 文件夹中,存放模型

 

 dockerfile 文件内容:

复制代码

# 使用 ASP.NET Core 6.0 基础镜像
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base

# 设置容器内的工作目录
WORKDIR /app

# 创建 Logs 目录
RUN mkdir -p /app/Logs

# 将 80 和 8900 端口暴露给外界
EXPOSE 80
EXPOSE 8900

# 使用较小的基础镜像来构建 Python
FROM debian:bullseye-slim AS python-build

# 安装 Python 的基本构建工具和依赖项,下载并安装 Python 3.12.3
RUN echo "deb http://mirrors.aliyun.com/debian/ bullseye main non-free contrib" > /etc/apt/sources.list && \
echo "deb http://mirrors.aliyun.com/debian-security bullseye-security main" >> /etc/apt/sources.list && \
echo "deb http://mirrors.aliyun.com/debian/ bullseye-updates main non-free contrib" >> /etc/apt/sources.list && \
apt-get update && apt-get install -y --no-install-recommends \
wget \
ca-certificates \
build-essential \
zlib1g-dev \
libffi-dev \
libssl-dev \
libbz2-dev \
libreadline-dev \
libsqlite3-dev \
libncurses5-dev \
libncursesw5-dev \
libgdbm-dev \
libdb5.3-dev \
libexpat1-dev \
liblzma-dev \
tk-dev \
libxml2-dev \
libxmlsec1-dev && \
update-ca-certificates && \
wget https://www.python.org/ftp/python/3.12.3/Python-3.12.3.tgz && \
tar -xf Python-3.12.3.tgz && \
cd Python-3.12.3 && \
./configure --enable-optimizations --enable-shared && \
make -j$(nproc) && \
make altinstall && \
cd .. && \
rm -rf Python-3.12.3 Python-3.12.3.tgz && \
apt-get purge -y --auto-remove wget build-essential && \
apt-get clean && rm -rf /var/lib/apt/lists/*


# 安装 Python 包
COPY requirements.txt .
RUN python3.12 -m pip install --upgrade pip && \
python3.12 -m pip install --no-cache-dir -r requirements.txt && \
python3.12 -m pip cache purge
# 验证 Python 安装和已安装的包
# RUN python3.12 --version && python3.12 -m pip list

# 清理 pip 缓存
# RUN python3.12 -m pip cache purge


# 使用最终的 ASP.NET Core 运行时基础镜像
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS final

# 设置容器内的工作目录
WORKDIR /app

# 将 80 端口暴露给外界
EXPOSE 80

# 从 python-build 镜像复制 Python 安装
COPY --from=python-build /usr/local /usr/local
# 设置环境变量以指向 Python 安装
ENV PYTHONHOME=/usr/local
ENV PATH="$PYTHONHOME/bin:$PATH"
ENV PYTHONPATH=$PYTHONHOME/lib/python3.12


# 复制应用程序代码到容器中
COPY . .

# 指定容器的入口点,启动你的 ASP.NET Core 应用程序
ENTRYPOINT ["dotnet", "LJCX.GeothermalHeat.Api.dll"]

复制代码

requirements.txt 文件存放需要安装包

six==1.16.0
joblib==1.4.0
numpy==1.26.4
pandas==2.2.2
scikit-learn==1.4.2
scipy==1.13.0
xgboost==2.0.3

5.构建镜像文件

docker build -t heatapi .
docker run -d -p 8080:80 -p 8900:8900 --name heat-api --restart=always --privileged=true -v /home/ljcx/heat_api/logs/:/app/Logs heat-api

 6.总结

通过 Pythonnet 在 .NET 6 项目中嵌套 Python 环境,可以有效地利用 Python 的机器学习能力来进行复杂的预测任务,如冬季供暖对室内温度的预测。这种跨语言的整合方法能够结合两种编程语言的优势,为开发者提供更灵活和高效的解决方案。

posted @   骑着蚂蚁快跑  阅读(161)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
点击右上角即可分享
微信分享提示