第一个python手写识别程序

我的第一个AI应用是参考实战:从0搭建完整 AI 开发环境写出第一个 AI 应用AI应用开发实战 - 从零开始配置环境两篇文章进行的实施,故以该文做出相应的补充。

遇到的问题

‘python’ 不是内部或外部变量

命令行执行python –version提示’python’ 不是内部或外部变量,在命令行中输入

1
set PATH="C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python36_64";%PATH%

之后,再输入

1
python --version

输出版本为3.6.5
但是关闭命令行之后,再输入python –version时,依旧提示 ‘python’ 不是内部或外部变量
故在计算机→属性右键→高级系统设置→环境变量→选择PATH→点击新建→将C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python36_64添加→确定,之后再运行python –version,显示正常。

saved_model.pb路径不对

单独参考第一篇文章进行配置时,发现没有samples-for-ai\export\saved_model.pb这个路径。
原因是没有启动examples\tensorflow\TensorflowExamples.sln这个解决方案,将MNIST项目设置为启动项目并运行,则会有samples-for-ai\export\saved_model.pb这个文件了。

命令行无响应

安装scipy-1.1.0mxnet_cu90-1.2.0时,命令行一直无响应,解决方案是到scipy-1.1.0mxnet-cu90 1.2.0下载指定的文件,然后通过pip3命令来执行安装,其余问题也可以通过类似命令来解决。

1
2
pip3 install D:\scipy-1.1.0-cp36-none-win_amd64.whl
pip3 install D:\mxnet_cu90-1.2.0-py2.py3-none-win_amd64.whl

通过下载的文件可以得知,文件较大,命令行无法及时完成下载,所以需要有一定的耐心等待

注意需要将C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python36_64\Scripts添加到PATH变量中。

cudnn版本不对

现在官网https://developer.nvidia.com/cudnn提供的cudnn版本是7.4.1,而微软示例代码中的cudnn版本是7.0.3,高版本的cudnn也会导致编译失败,需要找低版本的7.0.的cudnn替换到*C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v9.0\bin\cudnn64_7.dll

运行结果

解决了这部分问题之后,能正常展示winform界面,运行结果如下:
正确识别
错误识别
该部分涉及到训练模型是否足够多的问题,该文不做深入的研究。

总结

参考资料中提及的两篇文章都已经是做手写识别非常好的入门资料,该文仅仅是对这两篇文章做一个相应的补充,以作备忘。
另外我希望早日掌握以下技能

识别开心消消乐的游戏界面,然后通过能够确定执行的最佳下一步,达到这个目的,我觉得我对人工智能的了解和我的AI编程就进入了新的层次了。

#参考资料

用多项式解标准数独或锯齿数独

最近业余时间迷上了数独求解,所以试图用计算机的方式来解答数独。
接下来,我用四宫的数独为例子,示例怎么利用多项式求解数独。

四宫数独

我们以四宫的每个单元格标上序号,如下图所示
四宫数独
因为每行每列每宫都包含1,2,3,4且不重复。
所以第一行满足 x00+x01+x02+x03=10,x00*x01*x02*x03=24。
其余列的关系依次类推,其余宫的关系也是如此。
若数独题目如下图所示
四宫例子
根据坐标和格子的关系可知:
x00=1,x01=4,x14=1,x15=2

通过以下Python代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
from sympy import *
x00=Symbol('x00')
x01=Symbol('x01')
x02=Symbol('x02')
x03=Symbol('x03')
x04=Symbol('x04')
x05=Symbol('x05')
x06=Symbol('x06')
x07=Symbol('x07')
x08=Symbol('x08')
x09=Symbol('x09')
x10=Symbol('x10')
x11=Symbol('x11')
x12=Symbol('x12')
x13=Symbol('x13')
x14=Symbol('x14')
x15=Symbol('x15')
print(solve([
# 行之和为10
x00+x01+x02+x03-10,
x04+x05+x06+x07-10,
x08+x09+x10+x11-10,
x12+x13+x14+x15-10,

# 行之积为24
x00*x01*x02*x03-24,
x04*x05*x06*x07-24,
x08*x09*x10*x11-24,
x12*x13*x14*x15-24,

#列之和为10
x00+x04+x08+x12-10,
x01+x05+x09+x13-10,
x02+x06+x10+x14-10,
x03+x07+x11+x15-10,

#列之积为24
x00*x04*x08*x12-24,
x01*x05*x09*x13-24,
x02*x06*x10*x14-24,
x03*x07*x11*x15-24,

#宫之和为10
x00+x01+x04+x05-10,
x02+x03+x06+x07-10,
x08+x09+x12+x13-10,
x10+x11+x14+x15-10,

#宫之积为24
x00*x01*x04*x05-24,
x02*x03*x06*x07-24,
x08*x09*x12*x13-24,
x10*x11*x14*x15-24,

# x00=1,x01=4,x14=1,x15=2
x00-1,
x01-4,
x14-1,
x15-2
],[x00,x01,x02,x03,x04,x05,x06,x07,x08,x09,x10,x11,x12,x13,x14,x15]))

我们可以快速得知结果是

1
2
3
4
1,4,2,3,
3,2,4,1,
2,1,3,4,
4,3,1,2

其余标准数独(只有唯一解)的四宫数独也可以通过该种方式进行求解。

九宫数独

既然4宫可以用多项式求解?那么九宫是不是也可以这样呢?
答案是可以,但是又有点不同。
∵4+4+4+9=3+4+6+8=21
∵4*4*4*9=3*4*6*8=576
x1+x2+x3+x4+x5+x6+x7+x8+x9=45x1*x2*x3*x4*x5*x6*x7*x8*x9=362880
存在{1,2,3,4,5,6,7,8,9}和{1,2,4,4,4,5,7,9,9}两组解。
若我们把8当做-1看待,9当做-2看待
则每行每列每宫之变成了x1+x2+x3+x4+x5+x6+x7+x8+x9=1+2+3+4+5+6+7+(-1)+(-2)=25
则每行每列每宫之变成了x1*x2*x3*x4*x5*x6*x7*x8*x9=1*2*3*4*5*6*7*(-1)*(-2)=10080
参考四宫数独中Python代码的实现,可以写出(9行+9列+9宫)*(和表达式1个+积表达式1个)共54个表达式,
若已知提示数为N个,则加上这个N个表达式,则可以借助Python的强大的计算能力实现求解。
再将-1还原成8,-2还原成9,则完成了标准数独的求解。

锯齿数独

众所周知,DLX算法求解数独比回溯法要来得快很多,但是锯齿数独并不适合于用DLX算法(稀疏矩阵精准覆盖算法求解)
因为锯齿数独依旧满足每行每列1到9不重复,只是9个宫中9个来源的坐标有变化了。
若坐标序号如下图所示
数独下标示意

以下图第一宫为例:
锯齿数独示例

1
2
3
4
x00+x01+x02+x03+x09+x10+x18+x27+x28-25=0 //每宫之和为25  
x00*x01*x02*x03*x09*x10*x18*x27*x28-10080=0 //每宫之积为10080
x27-4=0 //x27=4
x03-(-2)=0 //先用-2代替9

其他宫的逻辑表达式依次类推,这样就能快速求解锯齿数独了。

推翻九宫结论

如下图有39个提示数的标准数独
九宫提示数

对应的python代码如下,仅仅实现了使CPU达到了100%的效果,迟迟出不来结果
所以该种方式求解9宫格的数独要么需要有强悍的电脑,要么还是直接使用DanceLink算法直接求解。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
from sympy import *
x00= Symbol('x00')
x01= Symbol('x01')
x02= Symbol('x02')
x03= Symbol('x03')
x04= Symbol('x04')
x05= Symbol('x05')
x06= Symbol('x06')
x07= Symbol('x07')
x08= Symbol('x08')
x09= Symbol('x09')
x10= Symbol('x10')
x11= Symbol('x11')
x12= Symbol('x12')
x13= Symbol('x13')
x14= Symbol('x14')
x15= Symbol('x15')
x16= Symbol('x16')
x17= Symbol('x17')
x18= Symbol('x18')
x19= Symbol('x19')
x20= Symbol('x20')
x21= Symbol('x21')
x22= Symbol('x22')
x23= Symbol('x23')
x24= Symbol('x24')
x25= Symbol('x25')
x26= Symbol('x26')
x27= Symbol('x27')
x28= Symbol('x28')
x29= Symbol('x29')
x30= Symbol('x30')
x31= Symbol('x31')
x32= Symbol('x32')
x33= Symbol('x33')
x34= Symbol('x34')
x35= Symbol('x35')
x36= Symbol('x36')
x37= Symbol('x37')
x38= Symbol('x38')
x39= Symbol('x39')
x40= Symbol('x40')
x41= Symbol('x41')
x42= Symbol('x42')
x43= Symbol('x43')
x44= Symbol('x44')
x45= Symbol('x45')
x46= Symbol('x46')
x47= Symbol('x47')
x48= Symbol('x48')
x49= Symbol('x49')
x50= Symbol('x50')
x51= Symbol('x51')
x52= Symbol('x52')
x53= Symbol('x53')
x54= Symbol('x54')
x55= Symbol('x55')
x56= Symbol('x56')
x57= Symbol('x57')
x58= Symbol('x58')
x59= Symbol('x59')
x60= Symbol('x60')
x61= Symbol('x61')
x62= Symbol('x62')
x63= Symbol('x63')
x64= Symbol('x64')
x65= Symbol('x65')
x66= Symbol('x66')
x67= Symbol('x67')
x68= Symbol('x68')
x69= Symbol('x69')
x70= Symbol('x70')
x71= Symbol('x71')
x72= Symbol('x72')
x73= Symbol('x73')
x74= Symbol('x74')
x75= Symbol('x75')
x76= Symbol('x76')
x77= Symbol('x77')
x78= Symbol('x78')
x79= Symbol('x79')
x80= Symbol('x80')
print(solve([
x00+x01+x02+x03+x04+x05+x06+x07+x08-25,
x00+x09+x18+x27+x36+x45+x54+x63+x72-25,
x00+x01+x02+x09+x10+x11+x18+x19+x20-25,
x00*x01*x02*x03*x04*x05*x06*x07*x08-10080,
x00*x09*x18*x27*x36*x45*x54*x63*x72-10080,
x00*x01*x02*x09*x10*x11*x18*x19*x20-10080,
x09+x10+x11+x12+x13+x14+x15+x16+x17-25,
x01+x10+x19+x28+x37+x46+x55+x64+x73-25,
x03+x04+x05+x12+x13+x14+x21+x22+x23-25,
x09*x10*x11*x12*x13*x14*x15*x16*x17-10080,
x01*x10*x19*x28*x37*x46*x55*x64*x73-10080,
x03*x04*x05*x12*x13*x14*x21*x22*x23-10080,
x18+x19+x20+x21+x22+x23+x24+x25+x26-25,
x02+x11+x20+x29+x38+x47+x56+x65+x74-25,
x06+x07+x08+x15+x16+x17+x24+x25+x26-25,
x18*x19*x20*x21*x22*x23*x24*x25*x26-10080,
x02*x11*x20*x29*x38*x47*x56*x65*x74-10080,
x06*x07*x08*x15*x16*x17*x24*x25*x26-10080,
x27+x28+x29+x30+x31+x32+x33+x34+x35-25,
x03+x12+x21+x30+x39+x48+x57+x66+x75-25,
x27+x28+x29+x36+x37+x38+x45+x46+x47-25,
x27*x28*x29*x30*x31*x32*x33*x34*x35-10080,
x03*x12*x21*x30*x39*x48*x57*x66*x75-10080,
x27*x28*x29*x36*x37*x38*x45*x46*x47-10080,
x36+x37+x38+x39+x40+x41+x42+x43+x44-25,
x04+x13+x22+x31+x40+x49+x58+x67+x76-25,
x30+x31+x32+x39+x40+x41+x48+x49+x50-25,
x36*x37*x38*x39*x40*x41*x42*x43*x44-10080,
x04*x13*x22*x31*x40*x49*x58*x67*x76-10080,
x30*x31*x32*x39*x40*x41*x48*x49*x50-10080,
x45+x46+x47+x48+x49+x50+x51+x52+x53-25,
x05+x14+x23+x32+x41+x50+x59+x68+x77-25,
x33+x34+x35+x42+x43+x44+x51+x52+x53-25,
x45*x46*x47*x48*x49*x50*x51*x52*x53-10080,
x05*x14*x23*x32*x41*x50*x59*x68*x77-10080,
x33*x34*x35*x42*x43*x44*x51*x52*x53-10080,
x54+x55+x56+x57+x58+x59+x60+x61+x62-25,
x06+x15+x24+x33+x42+x51+x60+x69+x78-25,
x54+x55+x56+x63+x64+x65+x72+x73+x74-25,
x54*x55*x56*x57*x58*x59*x60*x61*x62-10080,
x06*x15*x24*x33*x42*x51*x60*x69*x78-10080,
x54*x55*x56*x63*x64*x65*x72*x73*x74-10080,
x63+x64+x65+x66+x67+x68+x69+x70+x71-25,
x07+x16+x25+x34+x43+x52+x61+x70+x79-25,
x57+x58+x59+x66+x67+x68+x75+x76+x77-25,
x63*x64*x65*x66*x67*x68*x69*x70*x71-10080,
x07*x16*x25*x34*x43*x52*x61*x70*x79-10080,
x57*x58*x59*x66*x67*x68*x75*x76*x77-10080,
x72+x73+x74+x75+x76+x77+x78+x79+x80-25,
x08+x17+x26+x35+x44+x53+x62+x71+x80-25,
x60+x61+x62+x69+x70+x71+x78+x79+x80-25,
x72*x73*x74*x75*x76*x77*x78*x79*x80-10080,
x08*x17*x26*x35*x44*x53*x62*x71*x80-10080,
x60*x61*x62*x69*x70*x71*x78*x79*x80-10080,
x00-7,
x02-5,
x03-6,
x06+1,
x08-4,
x09-6,
x10-4,
x16-2,
x17-7,
x18-1,
x19-2,
x20+1,
x21-4,
x22-7,
x25-5,
x26-6,
x27-2,
x28-5,
x29-1,
x31-6,
x35+1,
x45+1,
x49-5,
x51-2,
x52-6,
x55+1,
x58-3,
x61-7,
x63-5,
x65-2,
x66-7,
x67-4,
x70+1,
x71-3,
x72-3,
x74-7,
x75-5,
x78-4,
x80-2,
1-1
],[x00,x01,x02,x03,x04,x05,x06,x07,x08,x09,x10,x11,x12,x13,x14,x15,x16,x17,x18,x19,x20,x21,x22,x23,x24,x25,x26,x27,x28,x29,x30,x31,x32,x33,x34,x35,x36,x37,x38,x39,x40,x41,x42,x43,x44,x45,x46,x47,x48,x49,x50,x51,x52,x53,x54,x55,x56,x57,x58,x59,x60,x61,x62,x63,x64,x65,x66,x67,x68,x69,x70,x71,x72,x73,x74,x75,x76,x77,x78,x79,x80]))

总结

这是我掌握的第三种通过计算机方式求解数独的第三种方式,前面两种分别是回溯法,DLX算法。
这种多项式求解的方法好处在于将数字之间的逻辑用多项式进行表达,将复杂的逻辑运算交由封装好的工具去处理。
稍微麻烦一点的就是书写多项式的表达式,通过数独的相关信息生成py文件再运行py文件,这是后话了。
该部分会在C#调用Python代码中会有详细介绍了(未完成,预计在2019年1月21日之前会补充这部分内容)。

最终总结

所有结论都需要实际验证正确之后,再形成文章,这是对自己的负责,也是对读者的负责。
也希望读者们能够不吝赐教,表示非常感谢!

python画爱心

该文算是python版的”Hello world”初探,故作相关的记录。
环境准备:Visual Studio 2017,python

正文

爱心一

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import numpy as np
import matplotlib.pyplot as plt

x_coords = np.linspace(- 100, 100, 500)
y_coords = np.linspace(- 100, 100, 500)
points = []

for y in y_coords:
for x in x_coords:
if((x* 0.03)** 2+(y* 0.03)** 2- 1)** 3-(x* 0.03)** 2*(y* 0.03)** 3<= 0:
points.append({ "x": x, "y": y})

heart_x = list(map( lambda point: point[ "x"], points))
heart_y = list(map( lambda point: point[ "y"], points))

plt.scatter(heart_x, heart_y, s= 10, alpha= 0.5)
plt.show()

效果如图
爱心1

爱心二

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#!/usr/bin/env python
# -*- coding:utf-8 -*-

import turtle
import time

# 画心形圆弧
def hart_arc():
for i in range(200):
turtle.right(1)
turtle.forward(2)

def move_pen_position(x, y):
turtle.hideturtle() # 隐藏画笔(先)
turtle.up() # 提笔
turtle.goto(x, y) # 移动画笔到指定起始坐标(窗口中心为0,0)
turtle.down() # 下笔
turtle.showturtle() # 显示画笔


#love = input("请输入表白话语,默认为‘I Love You’:")
#signature = input("请签署你的大名,不填写默认不显示:")

signature= ''
love = 'I Love You'

if love == '':
love = 'I Love You'

# 初始化
turtle.setup(width=800, height=500) # 窗口(画布)大小
turtle.color('red', 'pink') # 画笔颜色
turtle.pensize(3) # 画笔粗细
turtle.speed(1) # 描绘速度
# 初始化画笔起始坐标
move_pen_position(x=0,y=-180) # 移动画笔位置
turtle.left(140) # 向左旋转140度

turtle.begin_fill() # 标记背景填充位置

# 画心形直线( 左下方 )
turtle.forward(224) # 向前移动画笔,长度为224
# 画爱心圆弧
hart_arc() # 左侧圆弧
turtle.left(120) # 调整画笔角度
hart_arc() # 右侧圆弧
# 画心形直线( 右下方 )
turtle.forward(224)

turtle.end_fill() # 标记背景填充结束位置

# 在心形中写上表白话语
move_pen_position(0,0) # 表白语位置
turtle.hideturtle() # 隐藏画笔
turtle.color('#CD5C5C', 'pink') # 字体颜色
# font:设定字体、尺寸(电脑下存在的字体都可设置) align:中心对齐
turtle.write(love, font=('Arial', 30, 'bold'), align="center")

# 签写署名
if signature != '':
turtle.color('red', 'pink')
time.sleep(2)
move_pen_position(180, -180)
turtle.hideturtle() # 隐藏画笔
turtle.write(signature, font=('Arial', 20), align="center")

# 点击窗口关闭程序
window = turtle.Screen()
window.exitonclick()

效果如下图
爱心2

爱心三

1
2
3
4
5
6
7
8
9
10
11
12
13
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties
import numpy as np

x=np.linspace(-2,2,200)
y1 =np.sqrt(1-np.square(np.fabs(x)-1))
y2 =np.arccos(1-np.fabs(x))-np.pi

plt.plot(x,y1,'r',x,y2,'r')
plt.axis([-2.5,2.5,-3.5,1.5])

plt.title('hello world of python,copy from @andrew',fontsize=16)
plt.show()

效果如下图
爱心3

遇到问题

在visual studio 2017中命令行执行 pip install numpy 无效
在nuget程序包管理器控制台执行即可
pip install pyinstaller之后生成的exe无法执行
在我电脑上的路径是C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python36_64\Scripts,
把run.py拷贝到该目录,执行pyinstaller -F -W p . run.py解决问题

总结

暴击


参考资料

第一个AI应用

我的第一个AI应用是参考实战:从0搭建完整 AI 开发环境写出第一个 AI 应用AI应用开发实战 - 从零开始配置环境两篇文章进行的实施,故以该文做出相应的补充。

遇到的问题

‘python’ 不是内部或外部变量

命令行执行python –version提示’python’ 不是内部或外部变量,在命令行中输入

1
set PATH="C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python36_64";%PATH%

之后,再输入

1
python --version

输出版本为3.6.5
但是关闭命令行之后,再输入python –version时,依旧提示 ‘python’ 不是内部或外部变量
故在计算机→属性右键→高级系统设置→环境变量→选择PATH→点击新建→将C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python36_64添加→确定,之后再运行python –version,显示正常。

saved_model.pb路径不对

单独参考第一篇文章进行配置时,发现没有samples-for-ai\export\saved_model.pb这个路径。
原因是没有启动examples\tensorflow\TensorflowExamples.sln这个解决方案,将MNIST项目设置为启动项目并运行,则会有samples-for-ai\export\saved_model.pb这个文件了。

命令行无响应

安装scipy-1.1.0mxnet_cu90-1.2.0时,命令行一直无响应,解决方案是到scipy-1.1.0mxnet-cu90 1.2.0下载指定的文件,然后通过pip3命令来执行安装,其余问题也可以通过类似命令来解决。

1
2
pip3 install D:\scipy-1.1.0-cp36-none-win_amd64.whl
pip3 install D:\mxnet_cu90-1.2.0-py2.py3-none-win_amd64.whl

通过下载的文件可以得知,文件较大,命令行无法及时完成下载,所以需要有一定的耐心等待

注意需要将C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python36_64\Scripts添加到PATH变量中。

cudnn版本不对

现在官网https://developer.nvidia.com/cudnn提供的cudnn版本是7.4.1,而微软示例代码中的cudnn版本是7.0.3,高版本的cudnn也会导致编译失败,需要找低版本的7.0.的cudnn替换到*C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v9.0\bin\cudnn64_7.dll

运行结果

解决了这部分问题之后,能正常展示winform界面,运行结果如下:
正确识别
错误识别
该部分涉及到训练模型是否足够多的问题,该文不做深入的研究。

总结

参考资料中提及的两篇文章都已经是做手写识别非常好的入门资料,该文仅仅是对这两篇文章做一个相应的补充,以作备忘。
另外我希望早日掌握以下技能

识别开心消消乐的游戏界面,然后通过能够确定执行的最佳下一步,达到这个目的,我觉得我对人工智能的了解和我的AI编程就进入了新的层次了。

#参考资料