关键字:linux、桌面管理器、轻量级、openbox
时间:2017年5月

应用介绍

名称 说明
Openbox 桌面管理器
tint2 任务管理器
Wbar 桌面工具栏
iceweasel 浏览器
gThumb 图片浏览器
Leafpad 文本编辑器
PCMan File Manager 文件管理器
urxvtcd 控制台

安装

root@debian:~# apt-get install xorg openbox
root@debian:~# apt-get install tint2
root@debian:~# apt-get install wbar
root@debian:~# apt-get install iceweasel fonts-arphic-gkai00mp
root@debian:~# apt-get install gthumb
root@debian:~# apt-get install leafpad
root@debian:~# apt-get install pcmanfm
root@debian:~# apt-get install rxvt-unicode-ml

注:fonts-arphic-gkai00mp是中文字体,解决中文乱码问题。rxvt-unicode-ml是urxvtcd支持utf-8的版本。

配置

安装后,启动openbox,wbar自动启动了,但tint2没有自动启动。参考wbar的自动启动,配置tint2的自动启动。

root@debian:~# cd /etc/xdg/autostart
root@debian:/etc/xdg/autostart# ls -l
...
wbar.desktop
...
root@debian:/etc/xdg/autostart# cat wbar.desktop
[Desktop Entry]
Name=Warlock Bar
...
root@debian:/etc/xdg/autostart# vim tint2.desktop
[Desktop Entry]
Name=tint2
Type=Application
Exec=/usr/bin/tint2
Comment=Task bar.
root@debian:/etc/xdg/autostart# 

关键字:go、golang、http2、apns、推送、最简
时间:2017年5月

代码

package main

import (
    "crypto/tls"
    "fmt"
    "io/ioutil"
    "net/http"
    "strings"

    "golang.org/x/crypto/pkcs12"
    "golang.org/x/net/http2"
)

func main() {

    f, err := ioutil.ReadFile("./app.p12") // app.p12是推送证书
    if err != nil {
        fmt.Println("file error!")
        return
    }   

    privateKey, x509cert, err := pkcs12.Decode(f, "123456") // 123456是证书的密码
    if err != nil {
        fmt.Println("password error!")
        return
    }   

    tlscert := tls.Certificate{
        Certificate: [][]byte{x509cert.Raw},
        PrivateKey: privateKey,
        Leaf: x509cert,
    }   

    config := &tls.Config{
        Certificates: []tls.Certificate{tlscert},
    }   

    tr := &http2.Transport{TLSClientConfig: config}
    httpClient := http.Client{Transport: tr} 

    url := "https://api.push.apple.com/3/device/"
    token := "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
    payload := "{\"aps\":{\"alert\":\"hello\",\"sound\":\"msg_high.m4a\"}}"

    req, err := http.NewRequest("POST", url+token, strings.NewReader(payload))
    if err != nil {
        fmt.Println("new error")
        return
    }

    req.Header.Set("apns-topic", "com.xxx.appname") // com.xxx.appname是bundle id
    resp, err := httpClient.Do(req)
    if err != nil {
        fmt.Println("request error")
        return
    }
    defer resp.Body.Close()

    if resp.StatusCode == http.StatusOK {
        fmt.Println("apns-id: ", resp.Header.Get("apns-id"))
    } else {
        fmt.Println("response error")
        body, err := ioutil.ReadAll(resp.Body)
        if err!= nil{
            return
        }
        fmt.Println("resp.Body:\n", string(body))
    }
}

关键字:tensorflow、cnn、mnist、神经网络、卷积、验证码、识别
时间:2017年5月

目录

前言
CNN介绍
Tensorflow介绍
MNIST介绍
定义网络结构及参数
代码及说明
注意事项

前言

工作原因需要抓取一个网站的数据,但这个网站有验证码,很自然的想到了验证码识别。起初通过使用了一些常规的验证码识别的方法,但到了分割字符这一步是,发现非常困难。通过搜索发现了卷积神经网络可以很简单的完成识别工作,于是开始了卷积神经网络的学习。
继续向下阅读需要你对神经网络的基本概念有所认识。

CNN介绍

卷积神经网络(CNN),完全可以按字面去理解它,就是神经网络,并在网络中引入了卷积算法。CNN目前已经在图像识别上取得了广泛的应用。

Tensorflow介绍

Tensorflow是Google开源的一个神经网络框架,支持Python语言,是主流神经网络框架之一。

MNIST介绍

MNIST是一个非常好的分类算法研究的样本库。它由0~9的手写数字灰度图片构成,6万个训练样本,1万个测试样本。

定义网络结构及参数

这里采用了2层卷积和2层全连接构建网络结构。这是一个比较通用的层数,完全可以用于任意位数的验证码识别。但用于多位验证码图片识别时,需要调整输入层和输出层。

输入层(reshape) 输入节点: 784 输出节点: 28*28
隐层1(卷积) 输入节点: 28*28 输出节点: 32*14*14
隐层2(卷积) 输入节点: 32*14*14 输出节点: 64*7*7
隐层3(全连接) 输入节点: 64*7*7 输出节点: 1024
隐层4(全连接) 输入节点: 1024 输出节点: 10
输出层(Softmax) 输入节点: 10 输出节点: 10

代码及说明

tensor,是tensorflow的核心,tf.Variable()、tf.reshape()、tf.nn.relu()、tf.matmul()、tf.nn.softmax()、tf.reduce_mean()等,几乎所有函数的输入输出都是tensor,因此他们之间可以任意连接,构造网络。
reshape中的-1,对矩阵数据进行形状变换时,可以在一个维度上使用-1代替。例如:把一个[1,2,3,4,5,6,7,8,9,0]变成[[1,2,3,4,5],[6,7,8,9,0]],可以使用reshape(x,[2,5])或reshape(x,[-1,5])。

# -*- coding:utf-8 -*-
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data

X = tf.placeholder(tf.float32, [None, 784]) # 图片分辨率为28x28,但样本是
Y = tf.placeholder(tf.float32, [None, 10])
# placeholder(),占位函数,session.run的参数feed_dict={X: , Y:}中的X和Y对应的就是它。

inputs = tf.reshape(X,[-1,28,28,1])
# 样本是n个长度为784的1维向量,把它转成n个高28x宽28x通道数1的矩阵

#
# 第一层,卷积层
#
l1_weights = tf.Variable(tf.truncated_normal([5,5,1,32], stddev=0.1))
l1_biases = tf.Variable(tf.constant(0.1, shape=[32]))
# 卷积核[5,5],输入1张28x28图片,输出32张28x28特征图片

l1 = tf.nn.conv2d(inputs, l1_weights, strides=[1,1,1,1], padding='SAME') + l1_biases
# strides=[1,1,1,1],所有方向步进为1进行卷积
# padding='SAME',输出大小和输入大小相同28x28

l1 = tf.nn.relu(l1)
# 激活函数,例如:relu([0.5,-0.3,-0.13,1.2,-0.7] = [0.5,0,0,1.2,0]

l1 = tf.nn.max_pool(l1, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')
# 池化,strides=[1,2,2,1]使得输出为14x14

#
# 第二层,卷积层,与第一层类似
#
l2_weights = tf.Variable(tf.truncated_normal([5,5,32,64], stddev=0.1))
l2_biases = tf.Variable(tf.constant(0.1, shape=[64]))
# 卷积核[5,5],输入32张14x14图片,输出64张14x14特征图片

l2 = tf.nn.conv2d(l1, l2_weights, strides=[1,1,1,1], padding='SAME') + l2_biases
l2 = tf.nn.relu(l2)
l2 = tf.nn.max_pool(l2, ksize=[1,2,2,1], strides[1,2,2,1], padding='SAME')
# 池化,strides=[1,2,2,1]使得输出为7x7

#
# 第三层,全连接层
#
l3_weights = tf.Variable(tf.truncated_normal([7*7*64, 1024], stddev=0.1))
l3_biases = tf.Variable(tf.constant(0.1, shape=[1024]))
# 7*7*64个输入,1024个输出

l3 = tf.reshape(l2, [-1,7*7*64])
# 把64张7x7的特征转换成1维进行输入给全连接

l3 = tf.matmul(l3, l3_weights) + l3_biases
l3 = tf.nn.relu(l3)

#
#第四层,全连接层
#
l4_weights = tf.Variable(tf.truncated_normal([1024, 10], stddev=0.1))
l4_biases = tf.Variable(tf.constant(0.1, shape=[10]))
# 1024个输入,10个输出

l4 = tf.matmul(l3, l4_weights) + l4_biases # y = W * x + b

outputs = tf.nn.softmax(l4)
# softmax([1,2,2]) =  [1/(1+2+2),2/(1+2+2),2/(1+2+2)] = [0.2,0.4,0.4]

cross_entropy = -tf.reduce_sum(Y*tf.log(outputs)) # 计算交叉熵
train_op = tf.train.AdamOptimizer(0.0001).minimize(cross_entropy)

correct_prediction = tf.equal(tf.argmax(outputs, axis=1), tf.argmax(Y, axis=1))
# tf.argmax找某个轴上的最大值的位置,理解起来比较困难,简单理解就是把[1,0,0,0,0,0,0,0,0,0]转成[0],[0,1,0,0,0,0,0,0,0,0]转成[1],以此类推。
# tf.equal比较两个矩阵相同位置的值,相同为True,否则为False,例如:[[0,1],[1,0]]与[[0,0],[1,1]]比较,结果为[[True,False],[True,False]]

accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
# tf.cast()数据类型转换,True/False转成浮点1./0.

sess = tf.Session()
sess.run(tf.initialize_all_variables())

mnist = input_data.read_data_sets('MNIST_data', one_hot=True)
# 加载MNIST库,本地没有则从网络下载,下载完成后在当前目录有个MNIST_data/目录

for i in range(1000):
# 训练1000次
    batch_xs, batch_ys = mnist.train.next_batch(100)
    # 100个样本一批,进行1次训练
    sess.run(train_op, feed_dict={X:batch_xs, Y:batch_ys})
    if i%50==0:
        print "step %d, accuracy %f"%(i, sess.run(accuracy, feed_dict={X:batch_xs,Y:batch_ys}))
        # 每50次训练,输出准确率

print "test accuracy: ",sess.run(accuracy, feed_dict{X:mnist.test.images, Y:mnist.test.labels})
# 使用测试集计算准确率

注意事项

mnist样本库文件大小约10MB,但下载比较慢。
为了代码简单,没有加入tf.nn.dropout()、tf.train.Saver()等函数。tf.nn.dropout(),可防止过拟合。tf.train.Saver(),可以保存或回复模型,主要用于暂停训练和恢复训练,以及训练好的模型直接加载使用。

关键字:mnist、python、格式、转换、显示
时间:2017年5月

前言

MNIST是一个手写数字样本库,它主要用于图像识别的研究。它的格式方便于程序使用,但不能直接显示,如果需要显示必须进行转换。
OpenCV是使用最多的图像处理库,它实现了矩阵和图片之间的无缝转换。

MNIST数据格式

图片

图片10万张28×28图片->10万条长度为784的一维数组->长度为78400000的一维数组->按顺序写入数据文件

标签编码

0 => [1,0,0,0,0,0,0,0,0,0]
1 => [0,1,0,0,0,0,0,0,0,0]
2 => [0,0,1,0,0,0,0,0,0,0]
3 => [0,0,0,1,0,0,0,0,0,0]
4 => [0,0,0,0,1,0,0,0,0,0]
5 => [0,0,0,0,0,1,0,0,0,0]
6 => [0,0,0,0,0,0,1,0,0,0]
7 => [0,0,0,0,0,0,0,1,0,0]
8 => [0,0,0,0,0,0,0,0,1,0]
9 => [0,0,0,0,0,0,0,0,0,1]
注:这种编码格式,通俗的英文叫法是“one hot”。

代码

import cv2
import numpy as np
from matplotlib import pyplot as plt
from tensorflow.examples.turorials.mnist import input_data

convert = [[0],[1],[2],[3],[4],[5],[6],[7],[8],[9]] # 标签编码还原矩阵

mnist = input_data.read_data_sets('MNIST_data', one_hot=True)
for i in range(10):                                # 取10张图片数据
    batch_xs, batch_ys = mnist.train.next_batch(1) # 从训练集中取1条数据
    img = np.reshape(batch_xs, [28,28])            # 把1维数据还原成2维28x28的图片格式
    if i==0:
        img2 = img.copy()                          # 用第1张图来初始化img2变量
    else:
        img2 = np.column_stack([img2,img])         # 矩阵水平拼接,相当于图片水平拼接
    print np.dot(batch_ys, convert)                # 通过矩阵乘法把编码的标签还原成数字

img2 = cv2.cvtColor(img2, cv2.COLOR_GRAY2BGR)      # 转换成灰度图片
plt.imshow(img2)
plt.show()