keras 视频学习
https://morvanzhou.github.io/tutorials/machine-learning/keras/
学习此篇文章共花费了我1周的业余时间,幸好没丢人 有点结果了
1、下载数据部分
自己写了一个thinkphp 生成验证码,刚开始生成的比较负责,怎么训练都不行后来写得的比较简单,这样就能快速验证自己的模型是否正确
import os
from urllib import request
for idx in range(1000):
urlString ='http://www.code.com/public/index.php/index'
response = request.urlopen(urlString)
//由于thinkphp 验证码是单独的一个机制 本人也不太会php 所以就把验证码的值放在headers里面
imageName ='../data/'+ str(idx)+'_'+response.headers['code']+'.png'
with open(imageName,'wb') as img:
img.write(response.read())
2、处理数据
把数据弧度处理 并二值化 减小计算压力
import os
from PIL import Image
pics_dir='../data'
processed_pics_dir='./data'
# 将图片灰度化以减少计算压力
def preprocess_pics():
for (dirpath, dirnames, filenames) in os.walk(pics_dir):
for filename in filenames:
if filename.endswith('.png'):
with open(pics_dir + '/' + filename, 'rb') as f:
image = Image.open(f)
# 直接使用convert方法对图片进行灰度操作
image = image.convert('L')
image = convert_Image(image)
with open(processed_pics_dir + '/' + filename, 'wb') as of:
image.save(of)
def convert_Image(img, standard=127.5):
'''
【灰度转换】
'''
image = img.convert('L')
'''
【二值化】
根据阈值 standard , 将所有像素都置为 0(黑色) 或 255(白色), 便于接下来的分割
'''
pixels = image.load()
for x in range(image.width):
for y in range(image.height):
if pixels[x, y] > standard:
pixels[x, y] = 255
else:
pixels[x, y] = 0
return image
preprocess_pics() #会覆盖掉手动标注的数据请慎用
3、编写loadData 方法 以方便神经网络调用
import os
import random
import numpy as np
from PIL import Image
IMAGE_HEIGHT=30
IMAGE_WIDTH=110
captcha_chars = '01'
# captcha_chars = '0123456789'
char_idx_mappings = {}
idx_char_mappings = {}
for idx, c in enumerate(list(captcha_chars)):
char_idx_mappings[c] = idx
idx_char_mappings[idx] = c
MAX_CAPTCHA = 4 #验证码长度
CHAR_SET_LEN = len(captcha_chars)
# 验证码转化为向量
def text2vec(text):
text_len = len(text)
if text_len > MAX_CAPTCHA:
raise ValueError('验证码最长%d个字符'%MAX_CAPTCHA)
vector = np.zeros(MAX_CAPTCHA*CHAR_SET_LEN)
for i, c in enumerate(text):
idx = i * CHAR_SET_LEN + char_idx_mappings[c]
vector[idx] = 1
return vector
# 向量转化为验证码
def vec2text(vec):
text = []
vec[vec<0.5] = 0
char_pos = vec.nonzero()[0]
for i, c in enumerate(char_pos):
char_idx = c % CHAR_SET_LEN
text.append(idx_char_mappings[char_idx])
return ''.join(text)
# 向量转化为验证码
def vec2text1(vec):
text = []
for i in range(MAX_CAPTCHA):
data = vec[i*CHAR_SET_LEN:(i+1)*CHAR_SET_LEN]
index = data.tolist().index(max(data))
text.append(idx_char_mappings[index])
return ''.join(text)
# processed_pics_dir='../data'
processed_pics_dir='./data'
img_idx_filename_mappings = {}
img_idx_text_mappings = {}
img_idxes = []
index=0
# 首先遍历目录,根据文件名初始化idx->filename, idx->text的映射,同时初始化idx列表
for (dirpath, dirnames, filenames) in os.walk(processed_pics_dir):
for filename in filenames:
if filename.endswith('.png'):
idx = int(filename[0:filename.index('_')])
text = filename[int(filename.index('_')+1):int(filename.index('.'))]
img_idx_filename_mappings[idx] = filename
img_idx_text_mappings[idx] = text
img_idxes.append(idx)
# 为避免频繁读入文件,将images及labels缓存起来
sample_idx_image_mappings = {}
sample_idx_label_mappings = {}
# 提供给外部取得一批训练数据的接口
def get_batch_data(batch_size):
images = []
labels = []
target_idxes = random.sample(img_idxes, batch_size)
for target_idx in target_idxes:
image = None
if target_idx in sample_idx_image_mappings:
image = sample_idx_image_mappings[target_idx]
else:
with open(processed_pics_dir + '/' + img_idx_filename_mappings[target_idx], 'rb') as f:
image = Image.open(f)
image=image.convert('L')
# 对数据正则化,tensorflow处理时更高效
image = np.array(image)/255.0
sample_idx_image_mappings[target_idx] = image
label = None
if target_idx in sample_idx_label_mappings:
label = sample_idx_label_mappings[target_idx]
else:
label = text2vec(img_idx_text_mappings[target_idx])
sample_idx_label_mappings[target_idx] = label
images.append(image)
labels.append(label)
x = np.array(images)
y = np.array(labels)
return (x, y)
#测试部分 主要为了debug
(x,y)=get_batch_data(1)
#
print(y[0])
# print(x.reshape(-1, IMAGE_HEIGHT, IMAGE_WIDTH, 1).shape)
4、编写神经网络部分
from pathlib import Path
from keras.models import Sequential
from keras.layers import Dense, InputLayer, Activation
from keras.layers.core import Reshape, Dropout, Flatten
from keras.layers.convolutional import Conv2D
from keras.layers.pooling import MaxPooling2D
from keras.layers import Input, concatenate
from keras.models import Model
from keras.optimizers import Adam
import phpcode_data
model = Sequential()
model.add(InputLayer(input_shape=(phpcode_data.IMAGE_HEIGHT, phpcode_data.IMAGE_WIDTH)))
model.add(Reshape((phpcode_data.IMAGE_HEIGHT, phpcode_data.IMAGE_WIDTH, 1)))
# 三组卷积逻辑,每组包括两个卷积层及一个池化层
model.add(Conv2D(
filters=32,
kernel_size=5,
strides=(1, 1),
padding='same',
use_bias=True,
input_shape=(phpcode_data.IMAGE_HEIGHT, phpcode_data.IMAGE_WIDTH, 1)
))
model.add(Activation('relu'))
model.add(MaxPooling2D(
pool_size=2,
strides=2,
padding='same'
))
model.add(Conv2D(
filters=64,
kernel_size=5,
strides=(1, 1),
padding='same',
use_bias=True
))
model.add(Activation('relu'))
model.add(MaxPooling2D(
pool_size=2,
strides=2,
padding='same'
))
model.add(Conv2D(
filters=128,
kernel_size=5,
strides=(1, 1),
padding='same',
use_bias=True
))
model.add(Activation('relu'))
model.add(MaxPooling2D(
pool_size=2,
strides=2,
padding='same'
))
model.add(Flatten())
# 全连接层,输出维数是kaptcha_data.MAX_CAPTCHA * kaptcha_data.CHAR_SET_LEN
image_input = Input(shape=(phpcode_data.IMAGE_HEIGHT, phpcode_data.IMAGE_WIDTH))
encoded_image = model(image_input)
encoded_softmax = []
for i in range(phpcode_data.MAX_CAPTCHA):
out1 = Dense(128, activation="relu")(encoded_image)
output1 = Dense(phpcode_data.CHAR_SET_LEN, activation="softmax")(out1)
encoded_softmax.append(output1)
output = concatenate(encoded_softmax)
output1 = Dense(128,activation='relu')(output)
output2 = Dense(phpcode_data.MAX_CAPTCHA * phpcode_data.CHAR_SET_LEN,activation='softmax')(output1)
model = Model(inputs=[image_input], outputs=output2)
# model.add(Dense(1024))
# model.add(Activation('relu'))
#
# model.add(Dense(phpcode_data.MAX_CAPTCHA * phpcode_data.CHAR_SET_LEN))
# model.add(Activation('softmax'))
adam = Adam(lr=1e-4)
# 编译模型,损失函数使用categorical_crossentropy, 优化函数使用adadelta,每一次epoch度量accuracy
model.compile(loss='categorical_crossentropy', optimizer=adam, metrics=['accuracy'])
# 模型可视化
from keras.utils import plot_model
plot_model(model, to_file='captcha_recognition_model.png')
if Path('kaptcha_recognition.h5').is_file():
model.load_weights('kaptcha_recognition.h5')
batch_size = 100
for epoch in range(10000):
print("epoch {}...".format(epoch))
(x_train, y_train) = phpcode_data.get_batch_data(batch_size)
train_result = model.train_on_batch(x=x_train, y=y_train)
print(' loss: %.6f, accuracy: %.6f' % (train_result[0], train_result[1]))
if epoch % 5 == 0:
# 保存模型的权值`
model.save_weights('kaptcha_recognition.h5')
# 当准确率大于0.5时,说明学习到的模型已经可以投入实际使用,停止计算
5、验证部分
from pathlib import Path
import numpy as np
from PIL import Image
from keras import Sequential, Input, Model
from keras.engine import InputLayer
from keras.layers import Flatten, Dense, Activation, Conv2D, MaxPooling2D, concatenate, Reshape
from keras.optimizers import Adam
import phpcode_data
model = Sequential()
model.add(InputLayer(input_shape=(phpcode_data.IMAGE_HEIGHT, phpcode_data.IMAGE_WIDTH)))
model.add(Reshape((phpcode_data.IMAGE_HEIGHT, phpcode_data.IMAGE_WIDTH, 1)))
# 三组卷积逻辑,每组包括两个卷积层及一个池化层
model.add(Conv2D(
filters=32,
kernel_size=5,
strides=(1, 1),
padding='same',
use_bias=True,
input_shape=(phpcode_data.IMAGE_HEIGHT, phpcode_data.IMAGE_WIDTH, 1)
))
model.add(Activation('relu'))
model.add(MaxPooling2D(
pool_size=2,
strides=2,
padding='same'
))
model.add(Conv2D(
filters=64,
kernel_size=5,
strides=(1, 1),
padding='same',
use_bias=True
))
model.add(Activation('relu'))
model.add(MaxPooling2D(
pool_size=2,
strides=2,
padding='same'
))
model.add(Conv2D(
filters=128,
kernel_size=5,
strides=(1, 1),
padding='same',
use_bias=True
))
model.add(Activation('relu'))
model.add(MaxPooling2D(
pool_size=2,
strides=2,
padding='same'
))
model.add(Flatten())
# 全连接层,输出维数是kaptcha_data.MAX_CAPTCHA * kaptcha_data.CHAR_SET_LEN
image_input = Input(shape=(phpcode_data.IMAGE_HEIGHT, phpcode_data.IMAGE_WIDTH))
encoded_image = model(image_input)
encoded_softmax = []
for i in range(phpcode_data.MAX_CAPTCHA):
out1 = Dense(128, activation="relu")(encoded_image)
output1 = Dense(phpcode_data.CHAR_SET_LEN, activation="softmax")(out1)
encoded_softmax.append(output1)
output = concatenate(encoded_softmax)
output1 = Dense(128,activation='relu')(output)
output2 = Dense(phpcode_data.MAX_CAPTCHA * phpcode_data.CHAR_SET_LEN,activation='softmax')(output1)
model = Model(inputs=[image_input], outputs=output2)
adam = Adam(lr=1e-4)
# 编译模型,损失函数使用categorical_crossentropy, 优化函数使用adadelta,每一次epoch度量accuracy
model.compile(loss='categorical_crossentropy', optimizer=adam, metrics=['accuracy'])
if Path('kaptcha_recognition.h5').is_file():
model.load_weights('kaptcha_recognition.h5')
def get_single_image(filename):
images = []
with open(filename, 'rb') as f:
image = Image.open(f)
image = image.convert('L')
images.append(np.array(image)/255)
return np.array(images)
# 计算某一张图片的验证码
predicts = model.predict(get_single_image('data/82_1010.png'), batch_size=1)
print(predicts)
print('predict: %s' % phpcode_data.vec2text1(predicts[0]))
代码放在github上了 如果有人看到了 我希望能加我微信 咱们一起学习https://github.com/weihaigang/codeimage