前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >用于实现用python和django编写的图像分类的Keras UI

用于实现用python和django编写的图像分类的Keras UI

作者头像
代码医生工作室
发布2019-06-24 09:49:06
2.7K0
发布2019-06-24 09:49:06
举报
文章被收录于专栏:相约机器人相约机器人

KerasUI是一种可视化工具,可以在图像分类中轻松训练模型,并允许将模型作为服务使用,只需调用API。

https://github.com/zeppaman/KerasUI

主要特点:

  • 用oauth2验证
  • 允许完整的模型定制
  • 可以上传尚未训练的模型并通过API消费
  • 测试表格和视觉检查网络如何工作
  • 批量上传训练集

用法

  • 运行standalone.bat或sh standalone.bat(这将安装需求应用迁移并运行服务器,相同的脚本适用于UNIX和Windows)
  • 使用创建管理员用户 python manage.py createsuperuser
  • 导航到http://127.0.0.1:8000/

这需要python 3+,如果安装了多个版本,请根据(即pip3)更改脚本。

如何管理数据集

Keras UI允许将数据集项(图像)上载到Web应用程序中。您可以逐个执行此操作,也可以一次性添加包含许多图像的zip文件。它管理多个数据集,因此您可以将事物分开。加载图像后,可以单击“训练”按钮并运行训练过程。这将训练您定义的模型,而无需您进行任何交互。你将获得训练结果,如果你很挑剔,你可以转到日志文件,看看系统输出了什么

如何使用Web UI进行测试

为避免失眠,提供了一个简单的表格,可以上传图像并获得结果。

如何使用API UI或邮递员来测试API

在Web UI中看到的所有内容都可以使用API进行复制。

API使用情况

此应用程序使用oauth2来验证请求,因此需要的第一步是获取令牌。这是密码流的一个简单示例。请记住必须启用该应用程序(首次运行时不会默认创建)。

代码语言:javascript
复制
Assuming
client hUiSQJcR9ZrmWSecwh1gloi7pqGTOclss4GwIt1o
secret ZuuLK21sQ2uZxk8dVG7k6pO474FBlM6DEQs7FQvDh28gdLtbCDJwFFi0YlTlLsbz9ddjUa7Lun6ifYwkfwyGMD95WsCuzibFWIMpsZHMA039RIv1mOsYUO5nK5ZVv1hB
 
POST to http://127.0.0.1:8000/o/token/
 
Headers:
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded
 
Body:
grant_type:password
username:admin
password:admin2019!

回应是

代码语言:javascript
复制
{
    "access_token": "h6WeZwYwqahFDqGDRr6mcToyAm3Eae",
    "expires_in": 36000,
    "token_type": "Bearer",
    "scope": "read write",
    "refresh_token": "eg97atDWMfqC1lYKW81XCvltj0sism"
}

获取预测的API可以在json post或form post中使用。在json post中,图像以base64字符串形式发送。这种使用服务的双重方式非常有用,因为可以将其链接到表单或直接与wget或curl工具一起使用,也可以在应用程序中使用它。

代码语言:javascript
复制
POST http://127.0.0.1:8000/api/test/
 
Headers:
Content-Type:application/json
Authorization:Bearer <token>
 
Body
{
    "image":"<base 64 image",
    "dataset":1
}

响应

代码语言:javascript
复制
{
    "result": "<LABEL PREDICTED>"
}

教程

该项目是Codeproject上图像分类上下文的一部分。这里是技术部分的演练,解释它是如何构建的以及它是如何工作的。

项目堆栈:

  • python
  • django框架
  • keras,tensorflow,numpy
  • sqlite(或您喜欢的其他数据库)

使用的工具:

  • Visual Studio代码
  • 邮差
  • 一个Web浏览器

项目设置

该项目基于Django,因此首先要做的是使用CLI创建一个Django项目。这需要从pip安装Django。

代码语言:javascript
复制
django-admin startproject kerasui ' create the project

此命令将生成以下结构:

代码语言:javascript
复制
kerasui/
    manage.py
    kerasui/
        __init__.py
        settings.py
        urls.py
        wsgi.py

这些文件是:

  • 外部kerasui / root目录只是项目的容器。内部mysite /目录是项目的实际Python包。它的名称是需要用来导入其中任何内容的Python包名称(例如mysite.urls)。
  • manage.py:一个命令行实用程序,允许以各种方式与此Django项目进行交互。可以在jango-admin和manage.py中阅读有关manage.py的所有详细信息。
  • __init__.py:一个空文件,告诉Python该目录应该被视为Python包。如果是Python初学者,请阅读官方Python文档中有关包的更多信息。
  • kerasui / settings.py:此Django项目的设置/配置。Django设置将告诉有关设置如何工作的所有信息。
  • kerasui / urls.py:此Django项目的URL声明; Django支持的站点的“目录”。可以在URL调度程序中阅读有关URL的更多信息。
  • kerasui / wsgi.py:与WSGI兼容的Web服务器的入口点,用于为项目提供服务。有关更多详细信息,请参阅如何使用WSGI进行部署。

运行

要检查是否一切正常,只需使用内置服务器运行django

代码语言:javascript
复制
python manage.py runserver

也可以使用setup visual studio代码来运行django /

这是django配置:

代码语言:javascript
复制
{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Python: Django",
            "type": "python",
            "request": "launch",
            "program": "${workspaceFolder}\\kerasui\\manage.py",
            "args": [
                "runserver",
                "--noreload",
                "--nothreading"
            ],
            "django": true
        }
    ]
}

设置配置

这里配置的基本部分告诉:

  • 使用oauth 2和会话认证使:常规Web用户登录并使用网站和休息沙箱,API用户获取令牌并查询API服务
  • 使用SQLite(可以更改为移动到任何其他数据库)
  • 添加所有Django模块(以及两个自定义:管理UI和API)
  • 启用cors
代码语言:javascript
复制
INSTALLED_APPS = [
    'python_field',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'oauth2_provider',
    'corsheaders',
    'rest_framework',  
    'management',
    'api',
]
 
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
   # 'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'django.middleware.security.SecurityMiddleware',
    'corsheaders.middleware.CorsMiddleware',
]
 
ROOT_URLCONF = 'kerasui.urls'
 
 
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.BasicAuthentication',
        'oauth2_provider.contrib.rest_framework.OAuth2Authentication',
    ),
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    ),
  
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
    'PAGE_SIZE': 10,
}
 
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

第一次运行

Django使用迁移系统从您定义的模型生成迁移文件。要应用迁移,只需运行migrate命令(makemigration即可从模型创建迁移文件)。

用户数据库开始为空,因此需要创建admin用户才能登录。这是通过createsuperadmin命令完成的

代码语言:javascript
复制
python manage.py migrate
python manage.py createsuperuser
admin\admin2019!

它是如何构建的

该应用程序分为3个模块:

  • 管理部分: Web UI,模块和所有核心内容
  • 后台工作者:是一个可以在后台执行的Django命令,用于根据数据集训练模型
  • API:此部分公开API以从外部与应用程序交互。例如,这允许从第三方应用程序向数据集添加项目。此外,最常见的用法是发送图像并获得预测结果

管理

在Django上创建一个应用程序:

代码语言:javascript
复制
python manage.py startapp management

这将创建主文件。在这个模块中,使用的最多是模型和模型表示:

  • module.py:这里是所有具有现场规格的型号。通过这样的类定义,所有都被设置为对实体具有可用的CRUD
  • admin.py:此图层描述了如何使用表单显示和编辑数据。

数据模型非常简单。假设只想为每个数据集训练一个模型

  • DataSet:它包含模型,模型设置和数据集的名称。
  • DataSetItem:它包含数据集项,因此每行一个图像附加标签。

这里只是一个模型和模型表示的示例:

代码语言:javascript
复制
#from admin.py
class DataSetForm( forms.ModelForm ): 
 
 
    process =forms.CharField( widget=forms.Textarea(attrs={'rows':40, 'cols':115}), initial=settings.PROCESS_TEMPLATE )
    model_labels =forms.CharField(initial="[]")
    class Meta:
        model = DataSet
        fields = ['name', 'process','epochs','batchSize','verbose','model_labels','model']
        widgets = {
          'process': forms.Textarea(attrs={'rows':20, 'cols':200}),
          }
    
def train(modeladmin, request, queryset):
       for dataset in queryset:
        DataSetAdmin.train_async(dataset.id)
 
class DataSetAdmin(admin.ModelAdmin):
    list_display = ('name','epochs','batchSize','verbose','progress')
    inlines = [
      #  DataSetItemInline,
    ]
    form=DataSetForm
    actions = [train]
    change_list_template = "dataset_changelist.html"
 
 
    @staticmethod
    def train(datasetid):
        call_command('train',datasetid)
    @staticmethod
    def train_async(datasetid):
        t = threading.Thread(target=DataSetAdmin.train, args=(datasetid,))
        t.setDaemon(True)
        t.start()
 
 
admin.site.register(DataSet,DataSetAdmin)
 
#from model.py
 
class DataSet(models.Model):
    name= models.CharField(max_length=200)
    process = models.CharField(max_length=5000, default=settings.PROCESS_TEMPLATE)
    model = models.ImageField(upload_to=path_model_name,max_length=300,db_column='modelPath',blank=True, null=True)
    #weights = models.ImageField(upload_to=path_model_name,max_length=300,db_column='weightPath',blank=True, null=True)
    batchSize = models.IntegerField(validators=[MaxValueValidator(100), MinValueValidator(1)],default=10)
    epochs = models.IntegerField(validators=[MaxValueValidator(100), MinValueValidator(1)],default=10)
    verbose = models.BooleanField(default=True)
    progress = models.FloatField(default=0)    
    model_labels= models.CharField(max_length=200)
    def __str__(self):
        return self.name

Django采用代码优先方法,因此需要运行python manage.py makemigrations以生成将应用于数据库的迁移文件。

代码语言:javascript
复制
python manage.py makemigrations

背景工作者

要创建后台工作程序,需要一个模块来托管它,使用了管理模块。在其中需要创建一个management文件夹。其上的每个文件都可以python manage.py commandname通过API 运行或通过API 运行。

在例子中,通过常规的Django动作在后台进程中启动命令

这是相关部分:

代码语言:javascript
复制
class DataSetAdmin(admin.ModelAdmin):
   
    actions = [train]
 
 
    # ....
    
    @staticmethod
    def train(datasetid):
        call_command('train',datasetid)
    @staticmethod
    def train_async(datasetid):
        t = threading.Thread(target=DataSetAdmin.train, args=(datasetid,))
        t.setDaemon(True)
        t.start()

API

API是在一个单独的应用程序中创建的

代码语言:javascript
复制
python manage.py startapp API

基本上所有CRUD模型都可以通过API公开,但是需要指定如何序列化它

代码语言:javascript
复制
class DataSetItemSerializer(serializers.HyperlinkedModelSerializer):
    image = Base64ImageField()
    dataset=   serializers.PrimaryKeyRelatedField(many=False, read_only=True)
    class Meta:
        model = DataSetItem
 
        # Fields to expose via API
        fields = ('label', 'image', 'dataset')
 
 
class DataSetSerializer(serializers.HyperlinkedModelSerializer):  
   
    class Meta:
        model = DataSet
        fields = ('name', 'process')

还需要创建ViewSet模型和数据表示之间的映射:

代码语言:javascript
复制
class DataSetItemViewSet(viewsets.ModelViewSet):
   
    queryset = DataSetItem.objects.all()
    serializer_class = DataSetItemSerializer
 
class DataSetViewSet(viewsets.ModelViewSet):
   
    queryset = DataSet.objects.all()
    serializer_class = DataSetSerializer

最后需要定义所有路由并将viwset映射到url。这足以将模型用作api

代码语言:javascript
复制
router = routers.DefaultRouter()
router.register(r'users', views.UserViewSet)
router.register(r'datasetitem', views.DataSetItemViewSet)
router.register(r'dataset', views.DataSetViewSet)
router.register(r'test', views.TestItemViewSet, basename='test')
 
# Wire up our API using automatic URL routing.
# Additionally, we include login URLs for the browsable API.
urlpatterns = [
    url(r'^', include(router.urls)),
    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
]
 
urlpatterns += staticfiles_urlpatterns()

训练

算法非常简单:

  1. 从数据集中获取所有图像
  2. 将它们标准化并添加到带标签的列表中
  3. 创建模型在数据集模型中的指定方式
  4. 训练它

这是查询数据集项和加载图像的代码段:

代码语言:javascript
复制
def load_data(self, datasetid):
        self.stdout.write("loading images")
        train_data = []
        
        images = DataSetItem.objects.filter(dataset=datasetid)
        labels = [x['label'] for x in  DataSetItem.objects.values('label').distinct()]
      
        for image in images:
            self.stdout.write("Loading {0}".format(image.image))
            image_path = image.image.path
            if "DS_Store" not in image_path:           
                index=[x for x in range(len(labels)) if labels[x]==image.label]
                label = to_categorical([index,],len(labels))
                
                img = Image.open(image_path)
                img = img.convert('L')
                img = img.resize((self.IMAGE_SIZE, self.IMAGE_SIZE), Image.ANTIALIAS)
                train_data.append([np.array(img), np.array(label[0])])
            
        return train_data

看一眼:

代码语言:javascript
复制
labels = [x['label'] for x in  DataSetItem.objects.values('label').distinct()]
label = to_categorical([index,],len(labels))

这为所有标签分配了一个顺序,即["CAT","DOGS"]然后to_categorical将位置索引转换为单热表示。用简单的话说,这使得CAT = [1,0]和DOG = [0,1]

训练模型

代码语言:javascript
复制
   model=Sequential()
   exec(dataset.process)
   model.add(Dense(len(labels), activation = 'softmax'))
   model.fit(training_images, training_labels, batch_size=dataset.batchSize, epochs=dataset.epochs, verbose=dataset.verbose)

请注意,dataset.process是在Web管理员中输入的python模型定义,可以根据需要进行调整。最后一层添加到用户回调之外,以确保与数组大小匹配。

拟合方法只是使用所有数据运行训练(。

最后存储训练有素的模型:

代码语言:javascript
复制
datasetToSave=DataSet.objects.get(pk=datasetid)
datasetToSave.progress=100
datasetToSave.model_labels=json.dumps(labels)
temp_file_name=str(uuid.uuid4())+'.h5'
model.save(temp_file_name)
datasetToSave.model.save('weights.h5',File(open(temp_file_name, mode='rb')))
os.remove(temp_file_name)
datasetToSave.save()

请注意还保存标签顺序beacuse必须与模型相同才能匹配one-hot约定。

预测

有一种常见的方法,给定样本和数据集,检索模型,加载模型并进行预测。这是一段代码:

代码语言:javascript
复制
def predict(image_path,datasetid):
        
            dataset=DataSet.objects.get(pk=datasetid)
            modelpath=dataset.model.path
            model=load_model(modelpath)
            labels=json.loads(dataset.model_labels)
            
            img = Image.open(image_path)
            img = img.convert('L')
            img = img.resize((256, 256), Image.ANTIALIAS)
 
            result= model.predict(np.array(img).reshape(-1,256,256, 1))
            max=result[0]
            idx=0
            for i in range(1,len(result)):
                if max<result[i]:
                    max=result[i]
                    idx=i
 
 
            return labels[idx]

使用模型加载模型load_model(modelpath),标签来自数据库。模型预测输出作为值列表,选择较高的索引并用于检索在训练时分配给网络输出的正确标签。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-05-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 相约机器人 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档