标签 Ubuntu 下的文章

Kubernetes集群Pod使用Host的本地时区设置

Kubernetes集群搭建起来后,一直跑得很稳定。之前的关注点更多集中在安装配置组件调试方面,一些细枝末节被忽略了。Pod中时区的设置就是其中之一。今天腾出功夫打算解决一下这个问题。

一、问题现象

在我的Kubernetes 1.3.7集群的Master Node上,我们执行:

# date
Mon Feb 20 11:49:20 CST 2017

之后,在该Node上随意找到一个Pod中的Container,通过docker exec切入到容器内执行:

# docker exec -it 1975d68de07a /bin/bash
root@1975d68de07a:/# date
Mon Feb 20 03:49:53 UTC 2017

我们发现Docker内输出的当前date与Host上输出的date是不一致的。这对于K8s集群自身的运转似乎并没有多大影响,至少运行这么长时间以来,未出现因为时间设置与Host不同而导致的问题。但是对跑在Pod中应用来说,这个时间设置的问题可能会给业务的运行带来很多烦恼。

总之,一般来说,让Pod里的时间设置与Host上的Local time设置保持一致总是没错的。这里我们就来尝试解决这个问题。

二、Pod使用Host时区设置的方案

我有两个K8s集群环境,一个是基于ubuntu 14.04 node的k8s 1.3.7 环境,一个是基于ubuntu 16.04 node以kubeadm安装的k8s 1.5.1环境。由于ubuntu 14.04和ubuntu 16.04 Host在timezone的设置上略有差异,因此我们也要分为几种情况对应(redhat系的os这里暂不涉及,但原理是相同的):

0、ubuntu上时区设置

在Ubuntu上,/etc/localtime是系统的本地时区设置文件,直接影响到系统的当前date输出。不过在Ubuntu 14.04和Ubuntu 16.04上,这个文件的内容稍有不同:

在Ubuntu 14.04上,/etc/localtime就是一个regular file,其存储着本地时区的配置数据:

# file /etc/localtime
/etc/localtime: timezone data, version 2, 2 gmt time flags, 2 std time flags, no leap seconds, 16 transition times, 2 abbreviation chars

在我的Node上,其内容与/usr/share/zoneinfo/Asia/Shanghai指向的内容一致,好像/etc/localtime是这么得来的:

cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

而在Ubuntu 16.04上,/etc/localtime是一个symbolic link,链接到文件:/usr/share/zoneinfo/Asia/Shanghai

# file  /etc/localtime
/etc/localtime: symbolic link to /usr/share/zoneinfo/Asia/Shanghai

/usr/share/zoneinfo下存储着真正的时区设置文件,/usr/share/zoneinfo/Asia/Shanghai也是一个符号链接,指向的是/usr/share/zoneinfo/PRC:

# file /usr/share/zoneinfo/PRC
/usr/share/zoneinfo/PRC: timezone data, version 2, 2 gmt time flags, 2 std time flags, no leap seconds, 16 transition times, 2 abbreviation chars

在14.04 Node上,/etc/localtime与/usr/share/zoneinfo/PRC文件的内容是一模一样的。但在14.04的Pod中,这两个文件内容却是不同的:

# docker exec -it fe936562b6ee /bin/bash
# diff /etc/localtime /usr/share/zoneinfo/PRC
Binary files /etc/localtime and /usr/share/zoneinfo/PRC differ

因此,如果要让Pod使用的本地时区设置与Host的一致,就必须在Pod的manifest中做些“手脚”,接下来我们来分门别类地仔细看看。

1、Host 14.04,Pod 16.04

我们在14.04的node上随意run一个16.04的容器,可以看到:

# docker run -it ubuntu:16.04 /bin/bash
root@bf7cec08df23:/# ls -l /etc/localtime
lrwxrwxrwx 1 root root 27 Jan 19 16:33 /etc/localtime -> /usr/share/zoneinfo/Etc/UTC

容器内的系统时间与host时间是不一致的。

我们来创建一个使用ubuntu 16.04的docker image:

//1604pod-image-dockerfile
FROM ubuntu:16.04

CMD ["tail", "-f", "/var/log/bootstrap.log"]

在本地构建这个image:

# docker build -f ./1604pod-image-dockerfile -t 1604podimage:latest .
Sending build context to Docker daemon 5.632 kB
Step 1 : FROM ubuntu:16.04
 ---> f49eec89601e
Step 2 : CMD tail -f /var/log/bootstrap.log
 ---> Using cache
 ---> 06ffb5c85d7c
Successfully built 06ffb5c85d7c

# docker images|grep 1604pod
1604podimage                                                  latest              06ffb5c85d7c        28 minutes ago      129.5 MB

我们来编写这个运行于16.04之上的pod的manifest文件:

//1604-pod-on-1404-host.yaml

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: my-testpod
spec:
  replicas: 1
  template:
    metadata:
      labels:
        run: my-testpod
    spec:
      containers:
      - name: my-testpod
        image: 1604podimage:latest
        imagePullPolicy: IfNotPresent
        volumeMounts:
        - name: tz-config
          mountPath: /etc/localtime
      volumes:
      - name: tz-config
        hostPath:
          path: /usr/share/zoneinfo/Asia/Shanghai

我们将/usr/share/zoneinfo/Asia/Shanghai直接挂载为路径/etc/locatime了。创建该Pod并检查Pod内的系统时间:

# kubectl create -f 1604-pod-on-1404-host.yaml
deployment "my-testpod" created

# kubectl exec my-testpod-802169720-ehqlt date
Mon Feb 20 14:19:13 CST 2017

# date
Mon Feb 20 14:19:15 CST 2017

可以看出Pod内的系统时间与Host上的时间在时区上保持一致了。

2、Host 14.04, Pod 14.04

在ubuntu 14.04中,由于/etc/localtime自身就存储着时区设置,因此我们需要将其mount到Pod的对应位置中。我们的image demo如下:

//1404pod-image-dockerfile
FROM ubuntu:14.04

CMD ["tail", "-f", "/var/log/bootstrap.log"]

构建该image:

# docker build -f ./1404pod-image-dockerfile -t 1404podimage:latest .
Sending build context to Docker daemon 5.632 kB
Step 1 : FROM ubuntu:14.04
 ---> f2d8ce9fa988
Step 2 : CMD tail -f /var/log/bootstrap.log
 ---> Running in 6815ca6fe9d9
 ---> bc7f7de7690d
Removing intermediate container 6815ca6fe9d9
Successfully built bc7f7de7690d

# docker images|grep 1404pod
1404podimage                                                  latest              bc7f7de7690d        8 seconds ago       187.9 MB

Pod manifest如下:

//1404-pod-on-1404-host.yaml

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: my-testpod
spec:
  replicas: 1
  template:
    metadata:
      labels:
        run: my-testpod
    spec:
      containers:
      - name: my-testpod
        image: 1404podimage:latest
        imagePullPolicy: IfNotPresent
        volumeMounts:
        - name: tz-config
          mountPath: /etc/localtime
      volumes:
      - name: tz-config
        hostPath:
          path: /etc/localtime

可以看到,我们将host的/etc/locatime挂载到Pod内的/etc/localtime。创建该Pod后,我们查看一下Pod内的系统时间:

# kubectl exec my-testpod-2443385716-g9d4n date
Mon Feb 20 14:44:57 CST 2017

# date
Mon Feb 20 14:44:59 CST 2017

可以看出:两者在时区设置上已经一致了。

3、Host 16.04,Pod 16.04

由于有了上面的铺垫,后续的这两种情况,鉴于篇幅,我将简单描述。这里我们还将利用上面创建的两个image:1404podimage:latest和1604podimage:latest。

pod的manifest文件如下:

//1604-pod-on-1604-host.yaml

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: my-testpod
spec:
  replicas: 1
  template:
    metadata:
      labels:
        run: my-testpod
    spec:
      containers:
      - name: my-testpod
        image: 1604podimage:latest
        imagePullPolicy: IfNotPresent
        volumeMounts:
        - name: tz-config
          mountPath: /etc/localtime
      volumes:
      - name: tz-config
        hostPath:
          path: /usr/share/zoneinfo/Asia/Shanghai

创建该Pod后,查看系统时间:

# kubectl exec my-testpod-3193072711-7kwdl date
Mon Feb 20 14:55:00 CST 2017

# date
Mon Feb 20 14:55:31 CST 2017

主机和Pod内的系统时间在时区上一致了。

4、Host 16.04,Pod 14.04

pod的manifest文件如下:

//1404-pod-on-1604-host.yaml

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: my-testpod
spec:
  replicas: 1
  template:
    metadata:
      labels:
        run: my-testpod
    spec:
      containers:
      - name: my-testpod
        image: 1404podimage:latest
        imagePullPolicy: IfNotPresent
        volumeMounts:
        - name: tz-config
          mountPath: /etc/localtime
      volumes:
      - name: tz-config
        hostPath:
          path: /usr/share/zoneinfo/Asia/Shanghai

创建该Pod,对比Pod内时间和host时间:

# kubectl exec my-testpod-3024383045-xqbcv date
Mon Feb 20 14:58:54 CST 2017

# date
Mon Feb 20 14:58:49 CST 2017

主机和Pod内的系统时间在时区上一致了。

三、小结

上面所涉及到的manifest文件和Dockerfile文件源码在这里可以下载到,你可能需要根据你自己的k8s环境做些许改动。


微博:@tonybai_cn
微信公众号:iamtonybai
github.com账号: https://github.com/bigwhite

Kubernetes Pod无法挂载ceph RBD存储卷的临时解决方法

所有涉及到存储的地方都是极易出现“坑”的地方,Kubernetes也不例外。

一、问题起因

问题始于昨天升级一个stateful service的操作。该service下的Pod挂载了使用ceph RBD提供的一个Persistent Volume。该Pod是用普通deployment部署的,并没有使用处于alpha状态的PetSet。改动仅仅是image的版本发生了变化。我执行的操作如下:

# kubectl apply -f index-api.yaml

操作是成功的。但命令执行后,再次查看index-api这个Pod的状态,该Pod的状态长期处于:“ContainerCreating”,显然Pod没能重启成功。

进一步通过describe pod 检视events,发现如下Warning:

events:
  FirstSeen    LastSeen    Count    From            SubobjectPath    Type        Reason        Message
  ---------    --------    -----    ----            -------------    --------    ------        -------
  2m        2m        1    {default-scheduler }            Normal        Scheduled    Successfully assigned index-api-3362878852-9tm9j to 10.46.181.146
  11s        11s        1    {kubelet 10.46.181.146}            Warning        FailedMount    Unable to mount volumes for pod "index-api-3362878852-9tm9j_default(ad89c829-f40b-11e6-ad11-00163e1625a9)": timeout expired waiting for volumes to attach/mount for pod "index-api-3362878852-9tm9j"/"default". list of unattached/unmounted volumes=[index-api-pv]
  11s        11s        1    {kubelet 10.46.181.146}            Warning        FailedSync    Error syncing pod, skipping: timeout expired waiting for volumes to attach/mount for pod "index-api-3362878852-9tm9j"/"default". list of unattached/unmounted volumes=[index-api-pv]

index-api这个Pod尝试挂载index-api-pv这个pv超时,并失败。

二、问题探索和临时解决

首先查看问题pod所在Node(10.46.181.146)上的kubelet日志,kubelet负责与本地的docker engine以及其他本地服务交互:

... ...
I0216 13:59:27.380007    1159 reconciler.go:294] MountVolume operation started for volume "kubernetes.io/rbd/7e6c415a-f40c-11e6-ad11-00163e1625a9-index-api-pv" (spec.Name: "index-api-pv") to pod "7e6c415a-f40c-11e6-ad11-00163e1625a9" (UID: "7e6c415a-f40c-11e6-ad11-00163e1625a9").
E0216 13:59:27.393946    1159 disk_manager.go:56] failed to attach disk
E0216 13:59:27.394013    1159 rbd.go:228] rbd: failed to setup mount /var/lib/kubelet/pods/7e6c415a-f40c-11e6-ad11-00163e1625a9/volumes/kubernetes.io~rbd/index-api-pv rbd: image index-api-image is locked by other nodes
E0216 13:59:27.394121    1159 nestedpendingoperations.go:254] Operation for "\"kubernetes.io/rbd/7e6c415a-f40c-11e6-ad11-00163e1625a9-index-api-pv\" (\"7e6c415a-f40c-11e6-ad11-00163e1625a9\")" failed. No retries permitted until 2017-02-16 14:01:27.394076217 +0800 CST (durationBeforeRetry 2m0s). Error: MountVolume.SetUp failed for volume "kubernetes.io/rbd/7e6c415a-f40c-11e6-ad11-00163e1625a9-index-api-pv" (spec.Name: "index-api-pv") pod "7e6c415a-f40c-11e6-ad11-00163e1625a9" (UID: "7e6c415a-f40c-11e6-ad11-00163e1625a9") with: rbd: image index-api-image is locked by other nodes
E0216 13:59:32.695919    1159 kubelet.go:1958] Unable to mount volumes for pod "index-api-3362878852-pzxm8_default(7e6c415a-f40c-11e6-ad11-00163e1625a9)": timeout expired waiting for volumes to attach/mount for pod "index-api-3362878852-pzxm8"/"default". list of unattached/unmounted volumes=[index-api-pv]; skipping pod
E0216 13:59:32.696223    1159 pod_workers.go:183] Error syncing pod 7e6c415a-f40c-11e6-ad11-00163e1625a9, skipping: timeout expired waiting for volumes to attach/mount for pod "index-api-3362878852-pzxm8"/"default". list of unattached/unmounted volumes=[index-api-pv]
... ...

通过kubelet的日志我们可以看出调度到10.46.181.146这个Node上的index-api pod之所以无法挂载ceph RBD volume,是因为index-api-image已经被其他node锁住。

我的这个小集群一共就只有两个Node(10.46.181.146和10.47.136.60),那锁住index-api-image的就是10.47.136.60这个node了。我们查看一下平台上pv和pvc的状态:

# kubectl get pv
NAME           CAPACITY   ACCESSMODES   RECLAIMPOLICY   STATUS    CLAIM                   REASON    AGE
ceph-pv        1Gi        RWO           Recycle         Bound     default/ceph-claim                101d
index-api-pv   2Gi        RWO           Recycle         Bound     default/index-api-pvc             49d

# kubectl get pvc
NAME            STATUS    VOLUME         CAPACITY   ACCESSMODES   AGE
ceph-claim      Bound     ceph-pv        1Gi        RWO           101d
index-api-pvc   Bound     index-api-pv   2Gi        RWO           49d

index-api-pv和index-api-pvc的状态都是正常的,从这里看不出lock的情况。无奈我只能从ceph这个层面去查问题了!

index-api-image在mioss pool下面,我们利用ceph的rbd cli工具查看一下其状态:

# rbd ls mioss
index-api-image

# rbd info mioss/index-api-image
rbd image 'index-api-image':
    size 2048 MB in 512 objects
    order 22 (4096 kB objects)
    block_name_prefix: rb.0.5e36.1befd79f
    format: 1

# rbd disk-usage mioss/index-api-image
warning: fast-diff map is not enabled for index-api-image. operation may be slow.
NAME            PROVISIONED USED
index-api-image       2048M 168M

index-api-image状态ok。

如果你在执行rbd时,出现下面错误:

# rbd
rbd: error while loading shared libraries: /usr/lib/x86_64-linux-gnu/libicudata.so.52: invalid ELF header

可以通过重装libicu52这个包(这里演示的是基于ubuntu 14.04 amd64的版本)来解决:

# wget -c http://security.ubuntu.com/ubuntu/pool/main/i/icu/libicu52_52.1-3ubuntu0.4_amd64.deb
# dpkg -i ./libicu52_52.1-3ubuntu0.4_amd64.deb

回归正题!

经查manual发现,rbd提供了lock相关子命令可以查看image的lock list:

# rbd lock list  mioss/index-api-image
There is 1 exclusive lock on this image.
Locker       ID                       Address
client.24128 kubelet_lock_magic_node1 10.47.136.60:0/1864102866

真凶找到!我们看到位于10.47.136.60 node上有一个locker将该image锁住。我尝试重启10.47.136.60上的kubelet,发现重启后,lock依旧。

怎么取消这个锁呢?rbd不光提供了lock list命令,还提供了lock remove命令:

lock remove (lock rm)       Release a lock on an image

usage:
      lock remove image-spec lock-id locker
              Release a lock on an image. The lock id and locker are as output by lock ls.

开始解锁:

# rbd lock remove  mioss/index-api-image   kubelet_lock_magic_node1 client.24128

解锁成功后,delete掉那个处于ContainerCreating的Pod,然后index-api pod就启动成功了:

NAMESPACE                    NAME                                    READY     STATUS    RESTARTS   AGE       IP             NODE            LABELS
default                      index-api-3362878852-m6k0j              1/1       Running   0          10s       172.16.57.7    10.46.181.146   app=index-api,pod-template-hash=3362878852

三、问题简要分析

从问题现象来看,起因是由于index-api pod被从10.47.136.60这个node调度到 10.46.181.146这个node上而导致的。但是为什么image的lock没有释放的确怪异,因为我的index-api是捕捉pod退回信号,支持优雅退出的:

# kubectl delete -f index-api-deployment.yaml
deployment "index-api" deleted

2017/02/16 08:41:27 1 Received SIGTERM.
2017/02/16 08:41:27 1 [::]:30080 Listener closed.
2017/02/16 08:41:27 1 Waiting for connections to finish...
2017/02/16 08:41:27 [C] [asm_amd64.s:2086] ListenAndServe:  accept tcp [::]:30080: use of closed network connection 1
2017/02/16 08:41:27 [I] [engine.go:109] engine[mioss1(online)]: mioss1-29583fe44a637eabe4f865bc59bde44fa307e38e exit!
2017/02/16 08:41:27 [I] [engine.go:109] engine[wx81f621e486239f6b(online)]: wx81f621e486239f6b-58b5643015a5f337931aaa4a5f4db1b35ac784bb exit!
2017/02/16 08:41:27 [I] [engine.go:109] engine[wxa4d49c280cefd38c(online)]: wxa4d49c280cefd38c-f38959408617862ed69dab9ad04403cee9564353 exit!
2017/02/16 08:41:27 [D] [enginemgr.go:310] Search Engines exit ok

因此,初步猜测:这里很可能是kubernetes在监视和处理pod退出时,对于存储插件的状态处理存在一些bug,至于具体什么问题,还不得而知。

四、小结

对于像index-api service这样的stateful服务来说,使用普通deployment显然不能满足要求。Kubernetes在[1.3.0, 1.5.0)版本区间提供了处于alpha状态的PetSet controller,在1.5.0版本后,PetSet被改名为StatefulSet。与普通Pod不同,PetSet下面的每个Pet都有严格的身份属性,并根据身份属性绑定一定资源,并且不会像普通Pod那样被Kubernetes随意调度到任意Node上。

像index-api-service索引服务这样的一个实例绑定一个cephRBD pv的应用,特别适合使用PetSet或StatefulSet,不过我这里尚未测试用上PetSet后是否还会出现无法挂载rbd卷的问题。


微博:@tonybai_cn
微信公众号:iamtonybai
github.com账号: https://github.com/bigwhite

TensorFlow入门:零基础建立第一个神经网络

首先,我不得不承认这篇文章有些标题党的味道^0^,但文章还是要继续写下去,备忘也好,能帮助到一些人也好。

2016小结的时候,我说过:2017年要了解一些有关机器学习人工智能(以下简称AI)方面的技术。如果有童鞋问:Why?我会告诉你:跟风。作为技术人,关注和紧跟业界最前沿的技术总是没错的。

2016年被业界普遍认为是AI这一波高速发展的元年,当然DeepMindAlphaGo在这方面所起到的作用是功不可没的。不过人工智能并未仅仅停留在实验室,目前可以说人工智能已经深入到我们生活中的方方面面,比如:电商的精准个性化商品推荐、手机上安装的科大讯飞的中文语音识别引擎以及大名鼎鼎的Apple的siri等。只是普通老百姓并没有意识到这一点,或者说当前AI的存在和运行形式与大家传统思想中的“AI”还未到形似的地步,再或者当前AI的智能程度还未让人们感觉到AI时代的到来。

人工智能是当前的技术风口,也是投资风口。不过,人工智能技术与普通的IT技术不同的地方在于其背后需要大量且有一定深度的数学理论知识,有门槛,并且门槛较高,这会让普通程序员望而却步的。还好有国际大公司,比如:Google、Facebook等在努力在降低这一门槛,让人工智能技术更加接地气,让更多从事IT领域的人能接触到AI,并思考如何利用AI解决实际问题。Google的TensorFlow应该就是在这样的背景下诞生的。

这里并不打算介绍TensorFlow是什么,其原理是什么(因为目前我也不知道),只是利用TensorFlow简简单单地建立起一个神经网络模型,带着大家感性的认知一下什么是AI。本文特别适合那些像我一样,从未接触过AI,但又想感性认识AI的程序员童鞋们。

一、由来

和AI门外的程序员童鞋一样,想窥探AI的世界已久,但苦于没有引路人,一直在门外徘徊。直到看到martin gorner的那篇《TensorFlow and deep learning, without a PhD》。在这篇文章中,martin已经将利用TensorFlow建立并一步步训练优化一个神经网络的门槛降低到了最简化的程度了。不过即便这样,把martin所使用这个环境搭建起来(文中虽然有详细步骤),可能依旧会遇到一些问题,本文的目的之一就是帮助你迈过这“最后一公里”。

二、搭建环境

我所使用的环境是一台think center x86_64物理机,安装的是ubuntu 16.04.1。相关软件版本:

$ python
Python 2.7.12 (default, Nov 19 2016, 06:48:10)   

$ git version
git version 2.7.4

按照教程中INSTALL.txt中的步骤,我们需要安装依赖软件:

$ sudo  apt-get install python3
正在读取软件包列表... 完成
正在分析软件包的依赖关系树
正在读取状态信息... 完成
python3 已经是最新版 (3.5.1-3)。
升级了 0 个软件包,新安装了 0 个软件包,要卸载 0 个软件包,有 203 个软件包未被升级。

$ sudo apt-get install python3-matplotlib
python3-matplotlib 已经是最新版 (1.5.1-1ubuntu1)。

$sudo apt-get install python3-pip
python3-pip 已经是最新版 (8.1.1-2ubuntu0.4)。

$ pip3 install --upgrade tensorflow
Collecting tensorflow
  Downloading tensorflow-0.12.1-cp35-cp35m-manylinux1_x86_64.whl (43.1MB)
... ...
Installing collected packages: numpy, six, wheel, setuptools, protobuf, tensorflow
Successfully installed numpy-1.11.0 protobuf setuptools-20.7.0 six-1.10.0 tensorflow wheel-0.29.0

我们看到安装的TensorFlow是0.12.1版本,这应该是TensorFlow发布1.0版本前的最后一个Release版了。

下载Martin的教程代码:

$ mkdir -p ~/test/tensorflow

$ git clone https://github.com/martin-gorner/tensorflow-mnist-tutorial.git
正克隆到 'tensorflow-mnist-tutorial'...
remote: Counting objects: 271, done.
remote: Total 271 (delta 0), reused 0 (delta 0), pack-reused 271
接收对象中: 100% (271/271), 95.01 KiB | 46.00 KiB/s, 完成.
处理 delta 中: 100% (171/171), 完成.
检查连接... 完成。

我使用的tutorial的revision是:commit a9eb2bfcd74df4d7f3891d5403468d87547320e8。

三、建立并训练识别手写数字的神经网络

万事俱备,只差执行。

一起来建立我们的第一个神经网络:

$cd ~/test/tensorflow/tensorflow-mnist-tutorial
$ ls
cloudml          LICENSE                                mnist_2.2_five_layers_relu_lrdecay_dropout.py  mnist_4.1_batchnorm_five_layers_relu.py  tensorflowvisu_digits.py
CONTRIBUTING.md  mnist_1.0_softmax.py                   mnist_3.0_convolutional.py                     mnist_4.2_batchnorm_convolutional.py     tensorflowvisu.mplstyle
data             mnist_2.0_five_layers_sigmoid.py       mnist_3.1_convolutional_bigger_dropout.py      __pycache__                              tensorflowvisu.py
INSTALL.txt      mnist_2.1_five_layers_relu_lrdecay.py  mnist_4.0_batchnorm_five_layers_sigmoid.py     README.md                  

$ python3 mnist_1.0_softmax.py
/usr/lib/python3/dist-packages/matplotlib/font_manager.py:273: UserWarning: Matplotlib is building the font cache using fc-list. This may take a moment.
  warnings.warn('Matplotlib is building the font cache using fc-list. This may take a moment.')
/usr/lib/python3/dist-packages/matplotlib/font_manager.py:273: UserWarning: Matplotlib is building the font cache using fc-list. This may take a moment.
  warnings.warn('Matplotlib is building the font cache using fc-list. This may take a moment.')

Successfully downloaded train-images-idx3-ubyte.gz 9912422 bytes.
Extracting data/train-images-idx3-ubyte.gz
Successfully downloaded train-labels-idx1-ubyte.gz 28881 bytes.
Extracting data/train-labels-idx1-ubyte.gz
Successfully downloaded t10k-images-idx3-ubyte.gz 1648877 bytes.
Extracting data/t10k-images-idx3-ubyte.gz
Successfully downloaded t10k-labels-idx1-ubyte.gz 4542 bytes.
Extracting data/t10k-labels-idx1-ubyte.gz
Traceback (most recent call last):
  File "mnist_1.0_softmax.py", line 80, in <module>
    datavis = tensorflowvisu.MnistDataVis()
  File "/home/tonybai/test/tensorflow/tensorflow-mnist-tutorial/tensorflowvisu.py", line 166, in __init__
    self._color4 = self.__get_histogram_cyclecolor(histogram4colornum)
  File "/home/tonybai/test/tensorflow/tensorflow-mnist-tutorial/tensorflowvisu.py", line 160, in __get_histogram_cyclecolor
    colors = clist.by_key()['color']
AttributeError: 'Cycler' object has no attribute 'by_key'

出错了!

这里要注意的是:初次建立时,程序会首先从MNIST dataset下载训练数据文件,这里需要等待一段时间,千万别认为是程序出现什么hang住的异常情况。

之后的AttributeError才是真正的出错了!直觉告诉我是课程程序依赖的某个第三方库版本的问题,但又不知道是哪个库,于是我用临时处理方案fix it:

//tensorflowvisu.py
         #self._color4 = self.__get_histogram_cyclecolor(histogram4colornum)
         #self._color5 = self.__get_histogram_cyclecolor(histogram5colornum)
         self._color4 = '#CFF57F'
         self._color5 = '#E6C54A'

我把出错的调用注释掉,用hardcoding的方式直接赋值了两个color。

再次运行这个模型,我们终于看到那个展示训练过程的“高大上”的窗口弹了出来:

img{512x368}

运行一段时间后,当序号递增到2001时,程序hang住了。最初我以为是程序又出了错,最后在Martin的解释下,我才明白原来是训练结束了。在mnist_1.0_softmax.py文件末尾,我们可以看到这样一行注释:

# final max test accuracy = 0.9268 (10K iterations). Accuracy should peak above 0.92 in the first 2000 iterations.

这里告诉我们对神经网络的训练会进行多少次iterations。mnist_1.0_softmax.py需要2000次。tensorflow-mnist-tutorial下的每个训练程序文件末尾都有iteration次数,只不过有的说明简单些,有些复杂些罢了。

另外一个issue中,Martin也回应了上面的error问题,他的solution是:

pip3 install --upgrade matplotlib

我实测后,发现问题的确消失了!

四、小结

识别手写数字较为简单,采用softmax都可以将识别率训练到92%左右。采用其他几个模型,比如:mnist_4.1_batchnorm_five_layers_relu.py,可以将识别准确率提升到98%,甚至更高。

将这个教程运行起来的第一感觉就是AI真的很“高大上”,看着刷屏的日志和不断变化的UI,真有些科幻大片的赶脚,看起来也让你感觉心旷神怡。

不过目前仅仅停留在感性认知,深入理解TensorFlow背后的运行原理以及训练模型背后的理论才算是真正入门,这里仅仅是在AI领域迈出的一小步罢了^0^。




这里是Tony Bai的个人Blog,欢迎访问、订阅和留言!订阅Feed请点击上面图片

如果您觉得这里的文章对您有帮助,请扫描上方二维码进行捐赠,加油后的Tony Bai将会为您呈现更多精彩的文章,谢谢!

如果您喜欢通过微信App浏览本站内容,可以扫描下方二维码,订阅本站官方微信订阅号“iamtonybai”;点击二维码,可直达本人官方微博主页^_^:



本站Powered by Digital Ocean VPS。

选择Digital Ocean VPS主机,即可获得10美元现金充值,可免费使用两个月哟!

著名主机提供商Linode 10$优惠码:linode10,在这里注册即可免费获得。

阿里云推荐码:1WFZ0V立享9折!

View Tony Bai's profile on LinkedIn


文章

评论

  • 正在加载...

分类

标签

归档











更多