首页 > 其他分享 >scikit-learn与Serverless架构结合

scikit-learn与Serverless架构结合

时间:2023-01-26 15:44:35浏览次数:40  
标签:Serverless cut word scikit eve learn data

1 scikit-learn介绍

scikit-learn是一个面向Python的第三方提供的非常强力的机器学习库,简称sklearn,标志如下所示。它建立在NumPy、SciPy和Matplotlib上,包含从数据预处理到训练模型的各个方面。在人工智能算法开发过程中,研究人员不仅要开发模型,还要花很大力气在数据分析上,以根据数据特征进行算法选择。scikit-learn可以极大地节省编写代码的时间以及减少代码量,使开发者有更多的精力去分析数据、调整模型和修改超参,实现算法效率和效果之间的平衡。

scikit-learn学习库标志 

scikit-learn的安装和使用相对来说比较简单。开发者可以通过pip或者conda命令进行scikit-learn学习库的安装。

通过pip命令进行安装:

pip install -U scikit-learn

通过conda命令进行安装:

conda install -c conda-forge scikit-learn

另外需要注意的是,随着Python版本的不断升级迭代,最新版本的scikit-learn已经在逐渐抛弃对老版本的支持。从官方的推荐来看,scikit-learn1.0.1版本推荐使用Python 3.7及以上版本,同时依赖NumPy 1.14.6及以上版本、SciPy 1.1.0及以上版本、joblib 0.11及以上版本、threadpoolctl 2.0.0及以上版本等。

2 scikit-learn实践:鸢尾花数据分类

1.鸢尾花数据集

在scikit-learn中包含许多常用的数据集,本案例选择的是比较基础的鸢尾花(Iris)数据集。该数据集包含3种不同类型的鸢尾花(Setosa、Versicolour和Virginica),其花瓣和萼片长度存储在150×4的numpy.ndarray数组中,行表示样本,列表示各个特征,分别是萼片长度、萼片宽度、花瓣长度和花瓣宽度。我们可以通过Matplotlib进行数据可视化,以便进一步了解鸢尾花数据集。

import matplotlib.pyplot as plt 
from sklearn import datasets 
iris = datasets.load_iris() 
# 这里只选择其中两个特征进行展示 
X = iris.data[:, :2] 
y = iris.target 
x_min, x_max = X[:, 0].min() - 0.5, X[:, 0].max() + 0.5 
y_min, y_max = X[:, 1].min() - 0.5, X[:, 1].max() + 0.5 
plt.figure(2, figsize=(8, 6)) 
plt.clf() 
plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.Set1, edgecolor="k") 
plt.xlabel("Sepal length") 
plt.ylabel("Sepal width") 
plt.xlim(x_min, x_max) 
plt.ylim(y_min, y_max) 
plt.xticks(()) 
plt.yticks(()) 
plt.show()

得到的图像如下所示。

鸢尾花数据集展示 

2.使用决策树进行分类

决策树(Decision Tree)用于在已知各种情况发生概率的基础上,求取净现值的期望值大于等于0的概率,从而评价项目风险,判断其可行性。其是直观运用概率分析的一种图解法。由于这种决策分支画成图形很像一棵树的枝干,故称为决策树。在机器学习中,决策树是一个预测模型,它代表的是对象属性与对象值之间的一种映射关系。熵(Entropy)表示的是系统的凌乱程度。这一度量基于信息学理论中熵的概念。

决策树是一种树形结构,其中每个内部节点表示一个属性的测试,每个分支代表一个测试输出,每个叶节点代表一种类别。决策树是一种常用的分类方法。它是一种监督学习。所谓监督学习,就是给定一些样本,每个样本都有一组属性和一个类别,这些类别是事先确定的,通过学习得到一个分类器,这个分类器能够对新出现的对象给出正确的分类。

在scikit-learn学习库中应用决策树算法是非常简单和快捷的,只需要导入决策树相关的对象即可,例如:

from sklearn.tree import DecisionTreeClassifier

通过fit()方法,即可实现基础的数据训练操作,例如:

clf = DecisionTreeClassifier().fit(X, y)

针对鸢尾花分类,通过scikit-learn学习库使用决策树算法的完整代码:

from sklearn.datasets import load_iris 
from sklearn.tree import DecisionTreeClassifier 
from sklearn.metrics import accuracy_score 
import pickle 
# 加载数据,前120个样本作为训练集,后120个样本作为测试集 
iris = load_iris() 
X = iris.data[:120] 
y = iris.target[:120] 
test_X = iris.data[120:] 
test_y = iris.target[120:] 
# 训练 
clf = DecisionTreeClassifier().fit(X, y) 
# 保存 
save_path = r"./tree.dot" 
with open(r"./tree.dot", 'wb') as f:    
    pickle.dump(clf, f) 
# 加载模型 
    f = open(save_path, "rb") 
    tr = pickle.load(f) 
# 测试和预测 
    Z = tr.predict(test_X) 
    print("Accuracy: ", accuracy_score(test_y, Z))

上述代码先进行了鸢尾花数据集的加载,然后通过决策树算法进行建模、训练,并对模型结果进行保存,再通过加载模型,对测试集进行相关的准确率分析,最终得到结果:

Accuracy: 0.8

至此,通过scikit-learn实现了非常经典的案例:鸢尾花数据分类。

从这个案例中不难发现,传统意义上需要通过原生写法实现的决策树等算法,通过scikit-learn学习库对外暴露的接口,可以最大效率地进行数据集的加载、模型的训练,以及最终结果的预测。

与Serverless架构结合:文本分类

1.本地开发

文本分类是人工智能中非常经典的研究方向。实现一个简单的文本分类器,通常会被学习者认为是学习scikit-learn过程中的一个最佳实践。

本实践案例是基于scikit-learn实现一个根据公司主营业务的描述划分公司类型的功能,并将这个功能部署到Serverless架构,对外暴露服务级API。

在开始之前,准备一定的公司类型以及相关的数据,例如本案例将公司类型分成20类:

C000001——电力、热力、燃气及水生产和供应业

C000002——建筑业

C000003——批发和零售业

C000004——交通运输、仓储和邮政业

C000005——农、林、牧、渔业

C000006——采矿业

C000007——制造业

C000008——租赁和商务服务业

C000009——科学研究和技术服务业

C000010——水利、环境和公共设施管理业

C000011——居民服务、修理和其他服务业

C000012——住宿和餐饮业

C000013——信息传输、软件和信息技术服务业

C000014——金融业

C000015——房地产业

C000017——卫生和社会工作

C000018——教育

C000020——文化、体育和娱乐业

以上20类中,每一类都有数量一致的相关文本描述,例如“电力、热力、燃气及水生产和供应业”类别中就有类似下面案例的近百个主营业务描述。

·电线电缆、绝缘工具、仪器仪表、电力施工工具、五金电料、绝缘材料、安全防护用品的加工销售;劳保用品的销售。

·风力发电设备的销售、安装、维修、调试及技术服务;电力工程、机电安装工程的设计、施工及技术服务;机电一体化设备、机械设备、液压工具、五金交电、仪器仪表、电线电缆、电子产品、办公用品、日用百货、消防器材、防盗报警器材、服装鞋帽、劳保用品的销售;货物及技术的进出口业务。

……

在自然语言处理领域,基础数据集准备完成之后,往往还需要准备一定量的辅助资源,例如屏蔽一些语气词的停词库,因为部分语气词对模型训练和预测有影响。

在完成基本的数据和相关的辅助资源准备之后,可以进行业务逻辑的开发。整个业务逻辑开发主要包括3部分,分别是模型数据初始化、模型建立以及最终结果的预测。

1)模型数据初始化,导入训练集、停词库等相关数据:

def modelData(self):    
    class_list = []    
    cut_word_data = []    
    with open("StopwordsCN.txt") as f:        
        stop_word_data = [eve_stop_word.replace("\n", "") 
        for eve_stop_word in f.read-lines()]    
            for eve_dir in os.walk("Sample"):        
                eve_path_data = eve_dir[0]        
                for eve_file_data in eve_dir[2]:            
                    new_path_data = os.path.join(eve_path_data, eve_file_data)            
                    if ".txt" in new_path_data:                
                        with codecs.open(new_path_data, "r","utf-8") as f:                    
                            file_content = f.read()                
                            eve_content_fenci_data = []                
                            for eve_word_data in jieba.cut(file_content):                    
                                if eve_word_data not in stop_word_data and len(eve_word_data) > 0:                        
                                    eve_content_fenci_data.append(eve_word_data)                
                                    cut_word_data.append(" ".join(eve_content_fenci_data))                
                                    class_list.append(self.classDict[eve_path_data.split("/")[1]])    
                                    cut_word = pandas.DataFrame({"class": class_list, "content": cut_word_data})    
                                    countVectorizer = CountVectorizer(min_df=0, token_pattern=r"\b\w+\b")    
                                    textVector = countVectorizer.fit_transform(cut_word['content'])    
                                    return (cut_word, countVectorizer, textVector)

2)模型建立,主要通过scikit-learn提供的贝叶斯模型,进行多项式分布的朴素贝叶斯模型建立:

def setModel(self,textVector, cut_word):    

  bys = MultinomialNB()    

  bys.fit(textVector, cut_word["class"])    

  return bys

3)最终结果的预测,即根据模型以及用户待推理预测的内容,返回最终结果:

def predictModel(self,bys,companyInfor, countVectorizer):    

  newTexts = companyInfor    

  for i in range(len(newTexts)):        

    newTexts[i] = " ".join(jieba.cut(newTexts[i]))    

    return bys.predict(countVectorizer.transform(newTexts))

在本地进行测试,以某建筑业公司的主营业务描述文本“建筑装饰装修工程、建筑幕墙工程、防腐保温工程、金属门窗工程;钢结构工程、建筑防水工程、园林绿化工程、管道工程、机电设备安装工程、消防设施工程、建筑智能化工程的设计、施工;电梯安装。(依法须经批准的项目,经相关部门批准后方可开展经营活动。)”为例:

model = BYSModel()

cut_word, countVectorizer, textVector = model.modelData()

temp_data = ["建筑装饰装修工程、建筑幕墙工程、防腐保温工程、金属门窗工程;钢结构工程、建筑防水工程、园林绿化工程、管道工程、机电设备安装工程、消防设施工程、建筑智能化工程的设计、施工;电梯安装。(依法须经批准的项目,经相关部门批准后方可开展经营活动。)"]

category = model.predictModel(model.setModel(textVector, cut_word),temp_data, countVectorizer)

print(category)

运行结果为:

Building prefix dict from the default dictionary ...

Loading model from cache /var/folders/sb/frfgq4nx44n34b33jlzy1mj80000gn/T/jieba.cache

Loading model cost 0.543 seconds.

Prefix dict has been built successfully. ['建筑业']

可以看到,通过简单的数据处理以及基于scikit-learn进行模型建立,该项目已经可以正常进行符合预期的推理。

2.部署到Serverless架构

在将项目部署到Serverless架构之前,需要先按照Serverless架构的相关开发规范对业务逻辑进行升级,例如此处可以引入Bottle框架,进行参数的接收和结果的返回:

import Bottle 
model = BYSModel() 
cut_word, countVectorizer, textVector = model.modelData() 
@bottle.route('/company/category', method='POST') 
def category():    
    postData = json.loads(bottle.request.body.read().decode("utf-8"))    
    text = postData.get("text", None)    
    return model.predictModel(model.setModel(textVector, cut_word), [text], countVec-torizer) 
    app = bottle.default_app()

上面的代码是通过Bottle框架简单地将机器学习项目服务化。但是实际上,上面的代码还可包括部分优化操作,例如模型载入、初始化等相关操作:

model = BYSModel()

cut_word, countVectorizer, textVector = model.modelData()

上述两行代码并没有在category方法中执行,尽管这种做法会让实例启动时间有所增加,但是实际上在实例复用的时候,将会有比较明显的冷启动优化效果。

若使用Serverless Devs开发者工具进行项目的构建和部署,要根据Serverless Devs的相关规范对所需要的相关资源与运行路径进行描述:

edition: 1.0.0         
name: companyCategory                                      
#项目名称 
access: 'alibaba.default'                                  
#密钥别名 
services:    companyCategory:                                       
#服务名称        
component: devsapp/fc        
actions:                                           
#自定义执行逻辑            
pre-deploy:                                    
#在部署之前运行                
- run: s build --use-docker                
#要运行的命令行                    
path: ./                               
#命令行运行的路径            
post-deploy:                                   
#在部署之后运行                
- run: s nas command mkdir /mnt/auto/.s                    
path: ./                               
#命令行运行的路径                
- run: s nas upload -r -n ./.s/build/artifacts/company-category/server/.s/python /mnt/auto/.s/python    
#要运行的命令行                   
path: ./                               
#命令行运行的路径        
props:                                             
#组件的属性值            
region: cn-hangzhou            
service:                
  name: company-category                
  description: 公司主营业务分类                
  nasConfig: auto                
  vpcConfig: auto                
  logConfig: auto            
  function:                
    name: server                
    runtime: python3                
    codeUri: ./src                
    ossBucket: devsapp                
    handler: index.app                
    memorySize: 3072                
    timeout: 60            
    triggers:                
      - name: httpTrigger                
      type: http                
      config:                    
        authType: anonymous                    
        methods:                        
          - GET                        
          - POST            
          customDomains:                
            - domainName: auto                    
            protocol: HTTP                    
            routeConfigs:                        
              - path: /

上述Yaml文件中不仅有资源属性的定义,在actions字段下还包括若干行为定义,这使得在通过Serverless Devs开发者工具执行deploy命令之前,会先在Docker环境中执行项目的构建操作:

$ s build--use-docker

执行build操作的前提是,项目已经给出合理的依赖文件,例如requirements.txt等。以本项目为例,依赖详情包括:

bottle==0.12.19

jieba==0.42.1

pandas==1.1.5

scikit_learn==0.24.2

scipy==1.1.0

numpy==1.18

完成部署操作之后,系统会自动在NAS中创建目录,并上传相对应的文件夹等:

$ s nas command mkdir /mnt/auto/.s $ s nas upload -r -n ./.s/build/artifacts/company-category/server/.s/python /mnt/    auto/.s/python

当s deploy-y命令执行完成之后,即可完成Serverless项目的创建。项目创建成功后的日志如下所示。

Serverless项目创建完成后的日志 

此时,我们可以通过Postman工具对接口进行测试。以某交通运输公司的主营业务描述“普通货物仓储、配载;普通货物运输;货运代理服务”为例,测试结果如下所示。

通过Postman进行项目测试 

可以看到,系统已经正确地输出相关的结果:交通运输、仓储和邮政业。

至此,基于scikit-learn学习库,在Serverless架构上成功部署了一个根据企业信息进行企业分类的自然语言处理项目,并对外提供API服务。

3.项目优化

虽然通过Serverless Devs开发者工具,本项目可以非常简单、快速、方便地部署到Server-less架构,但也有着比较多的优化空间,例如项目被部署到阿里云函数计算的Python运行时上,在部署前后将会面临诸多环境问题。

·部署前:机器学习项目往往存在部分不可跨平台使用的依赖库,此时我们需要了解线上实例的环境详情,或者使用相对应的工具模拟线上实例环境,进行依赖的安装、项目的构建。

·部署后:项目将会受到运行时环境的影响,而很难随着整体的技术迭代发展,例如目前阿里云函数计算的Python运行时版本是3.6,而很多依赖库没办法在Python 3.6版本下正常运作,例如最新的scikit-learn已经推荐使用Python 3.7及以上版本。

针对这类问题,可以考虑通过容器镜像的方法进行解决,即将项目打包成容器镜像部署到函数计算,这样可以最大限度地提高项目后期的灵活度,以及降低维护成本等。

 

标签:Serverless,cut,word,scikit,eve,learn,data
From: https://www.cnblogs.com/muzinan110/p/17067861.html

相关文章

  • Serverless架构下的AI应用
    近年来,Serverless架构逐渐被更多的开发者所认识、接受,逐渐被应用到了更多领域,其中包括如今非常热门的机器学习领域。与其他领域不同的是,在Serverless架构上进行人工智能相......
  • Serverless架构下的应用开发流程
    UCBerkeley认为Serverless架构的出现过程类似于40多年前从汇编语言转向高级语言的过程,在未来Serverless架构的使用会飙升,或许服务器式云计算不会消失,但是将促进BaaS发展,以......
  • Serverless面临的挑战
    在Serverless架构为使用者提供全新的编程范式的同时,当用户在享受Serverless带来的第一波技术红利的时候,Serverless的缺点也逐渐地暴露了出来,例如函数的冷启动问题,就是如今......
  • Serverless架构下用Python轻松实现图像分类和预测
    Serverless架构下用Python轻松实现图像分类和预测图像分类是人工智能领域的一个热门话题。通俗解释就是,图像分类是一种根据各自在图像信息中所反映的不同特征,把不同类别的......
  • Serverless 触发器和函数赋能自动化运维
    Serverless架构在运维层面有着得天独厚的优势,不仅因为其事件触发可以有针对性地获取、响应一些事件,还因为其轻量化、低运维的特性让很多运维开发者甚是喜爱。在实际生产中......
  • Serverless与监控告警、自动化运维
    通过Serverless架构实现监控告警功能在实际生产中,经常需要编写一些监控脚本来监控网站服务或API服务的健康状况,包括是否可用、响应速度是否足够快等。传统的方法是直接使......
  • Serverless Workflow
    ServerlessWorkflowServerlessWorkflow(Serverless工作流)是一个用来协调多个分布式任务执行的全托管云服务。如图4-21所示,在Serverless工作流中,用户可以用顺序、分支、......
  • Serverless可观测性
    4.3.3可观测性Serverless应用的可观测性是被很多用户所关注的。可观测性是通过外部表现判断系统内部状态来衡量的。在应用开发中,可观测性帮助用户判断系统内部的健康状......
  • Serverless应用优化
    Serverless应用优化4.4.1资源评估依旧重要Serverless架构虽然是按量付费的,但是并不代表它就一定比传统的服务器租用费用低。如果对自己的项目评估不准确,对一些指标设置......
  • Serverless传统Web框架迁移
    与其说Serverless架构是一个新的概念/架构,不如说它是一个全新的思路、一种新的编程范式。在这种新的架构或者说新的编程范式下,使用全新的思路来做Serverless应用是再好不过......