学人工智能一次竞赛都不打？闹呢？

#第一届汉字书法识别挑战赛#

4.24 榜单

100个汉字的训练集

10000张书法图片的测试集

1defmove_ratio(data_list, original_str, replace_str):

2forxindata_list:

3fromImage = Image.open(x)

4x = x.replace(original_str, replace_str)

5fromImage.save(x)

3mkdir -p valid_dir/\$d/

5done;

6done

cnn一把梭

1# bn + prelu

2defbn_prelu(x):

3x = BatchNormalization()(x)

4x = PReLU()(x)

5returnx

6# build baseline model

7defbuild_model(out_dims, input_shape=(128,128,1)):

8inputs_dim = Input(input_shape)

9x = Conv2D(32, (3,3), strides=(2,2), padding='valid')(inputs_dim)

10x = bn_prelu(x)

11x = Conv2D(32, (3,3), strides=(1,1), padding='valid')(x)

12x = bn_prelu(x)

13x = MaxPool2D(pool_size=(2,2))(x)

14x = Conv2D(64, (3,3), strides=(1,1), padding='valid')(x)

15x = bn_prelu(x)

16x = Conv2D(64, (3,3), strides=(1,1), padding='valid')(x)

17x = bn_prelu(x)

18x = MaxPool2D(pool_size=(2,2))(x)

19x = Conv2D(128, (3,3), strides=(1,1), padding='valid')(x)

20x = bn_prelu(x)

21x = MaxPool2D(pool_size=(2,2))(x)

22x = Conv2D(128, (3,3), strides=(1,1), padding='valid')(x)

23x = bn_prelu(x)

24x = AveragePooling2D(pool_size=(2,2))(x)

25x_flat = Flatten()(x)

26fc1 = Dense(512)(x_flat)

27fc1 = bn_prelu(fc1)

28dp_1 = Dropout(0.3)(fc1)

29fc2 = Dense(out_dims)(dp_1)

30fc2 = Activation('softmax')(fc2)

31model = Model(inputs=inputs_dim, outputs=fc2)

32returnmodel

1defresnet50_100(feat_dims, out_dims):

2# resnett50 only have a input_shape=(128, 128, 3), if use resnet we must change

3# shape at least shape=(197, 197, 1)

4resnet_base_model = ResNet50(include_top=False, weights=None, input_shape=(128,128,1))

5# get output of original resnet50

6x = resnet_base_model.get_layer('avg_pool').output

7x = Flatten()(x)

8fc = Dense(feat_dims)(x)

9x = bn_prelu(fc)

10x = Dropout(0.5)(x)

11x = Dense(out_dims)(x)

12x = Activation("softmax")(x)

13# buid myself model

14input_shape = resnet_base_model.input

15output_shape = x

16resnet50_100_model = Model(inputs=input_shape, outputs=output_shape)

17returnresnet50_100_model

loss

acc

github地址：https://github.com/FlyEgle/chinese_font_recognition/

1condainstall -c https://conda.binstar.org/menpo opencv

1importos

2importnumpyasnp

3importtorch

4importtorch.utils.dataasdata

5importcv2

6fromPILimportImage

7fromtqdmimporttqdm

8trainpath ='E:\\Code\\TMD1st\\train\\'#这是我的储存路径，windows下的路径是需要用\\隔开的，linux是反斜杠/

9testpath ='E:\\Code\\TMD1st\\test1\\'

10words = os.listdir(trainpath)# 按时间排序 从早到晚

11category_number = len(words)# 一共有多少个字

12img_size = (256,256)#将图片大小统一设定为这个值

14path = trainpath + words[order] +'\\'

15files = os.listdir(path)

16datas = []

17forfileinfiles:

18file = path + file

19img = np.asarray(Image.open(file))

20img = cv2.resize(img, img_size)

21datas.append(img)

22datas = np.array(datas)

23labels = np.zeros([len(datas), len(words)], dtype=np.uint8)

24labels[:, order] =1

25returndatas, labels

26deftransData():#将所有数据转存，以后就不用每次都从原始数据读取了

27num = len(words)

28datas = np.array([], dtype=np.uint8)

29datas.shape =-1,256,256

30labels = np.array([], dtype=np.uint8)

31labels.shape =-1,100

32forkinrange(num):

34datas = np.append(datas, data, axis=)

35labels = np.append(labels, label, axis=)

37np.save('data.npy', datas)#将数据和标签分别存为data和label

38np.save('label.npy', labels)

1if__name__ =='__main__':

4index = np.arange(,len(datas),1, dtype=np.int)

5print(datas.shape, labels.shape)

(40000, 256, 256) (40000, 100)

1classTrainSet(data.Dataset):

2def__init__(self, eval=False):

5index = np.arange(, len(datas),1, dtype=np.int)#换one-hot为label

6np.random.seed(123)

7np.random.shuffle(index)

8ifeval:#如果eval为真，就取10%作为验证集，设定随机数种子是为了每次取出来的都是固定的10%,以免将验证集用于训练

9index = index[:int(len(datas) *.1)]

10else:

11index = index[int(len(datas) *.1):]

12self.data = datas[index]

13self.label = labels[index]

14np.random.seed()

15def__getitem__(self, index):

16returntorch.from_numpy(self.data[index]), \

17torch.from_numpy(self.label[index])

18def__len__(self):

19returnlen(self.data)

1importtorch

2importtorch.optimasoptim

4importtorch.nnasnn

5importdata

6importtorch.nn.functionalasF

7n_epoch, batch_size =25,8# 设置遍历次数及每个batch的大小

8trainset = data.TrainSet(eval=False)#实例化上面定义的数据集对象

10evalset = data.TrainSet(eval=True)#验证集

12net = Net()# 实例化模型

13iftorch.cuda.is_available():# 将模型移到GPU上

14net.cuda()

15criterion = nn.CrossEntropyLoss()#损失函数使用交叉熵

16optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=1e-1, weight_decay=1e-4)#优化器使用SGD 学习率1e-3

17deftrain(epoch):

18net.train()# 经模型切换到训练模式

19correct =

20sum =

22labels = labels.max(1)[1]

23datas = Variable(datas).float()

24datas = datas.view(-1,1,256,256)

25labels = Variable(labels).long()

26iftorch.cuda.is_available():#数据转移到GPU

27datas = datas.cuda()

28labels = labels.cuda()

30outputs = net(datas)# 前项计算

31loss = criterion(outputs, labels)# 根据结果和label计算损失函数

32loss.backward()# 做反向传播

33optimizer.step()# 用优化器进行一次更新

34pred_choice = outputs.data.max(1)[1]# 前向输出计算最大的一个作为最可能的输出

35correct += pred_choice.eq(labels.data).cpu().sum()# 统计正确个数

36sum += len(labels)# 总数

37# 输出每次计算的信息

39'Train epoch: [%d]'% (epoch),

40# 'acc:%.4f p:%.4f r:%.4f F1:%.4f' % (acc, p, r, F1),

41'correct/sum:%d/%d, %.4f'% (correct, sum, correct / sum))

42defeval(epoch):# 用验证集做类似过程，只是不计算梯度、不更新参数

43net.eval()

44correct =

45sum =

47labels = labels.max(1)[1]

48datas = Variable(datas).cuda().float()

49datas = datas.view(-1,1,256,256)

50labels = Variable(labels).cuda().long()

52outputs = net(datas)

53# loss = criterion(outputs, labels)

54# loss.backward()

55# optimizer.step()

56pred_choice = outputs.data.max(1)[1]

57correct += pred_choice.eq(labels.data).cpu().sum()

58sum += len(labels)

60'Eval epoch: [%d]'% (epoch),

61# 'acc:%.4f p:%.4f r:%.4f F1:%.4f' % (acc, p, r, F1),

62'correct/sum:%d/%d, %.4f'% (correct, sum, correct / sum))

63if__name__ =='__main__':

64forepochinrange(n_epoch):

65train(epoch)

66eval(epoch)

1classnet(nn.Module):

2def__init__(self):

3super(net,self).__init__()

4self.pool = nn.MaxPool2d(2)

5self.drop = nn.Dropout(p=.5)

7self.norm1 = nn.BatchNorm2d(32)

9self.norm2 = nn.BatchNorm2d(32)

11self.norm3 = nn.BatchNorm2d(64)

12# Sequential 是连续操作的写法

14nn.BatchNorm2d(128),

15nn.ReLU(),

17nn.BatchNorm2d(128),

18nn.ReLU(),

19)

20self.out_layers = nn.Sequential(nn.Linear(128*8*8,1024),

21nn.BatchNorm1d(1024),

22nn.ReLU(),

23nn.Linear(1024,256),

24nn.BatchNorm1d(256),

25nn.ReLU(),

26nn.Linear(256,100),

27nn.BatchNorm1d(100),

28nn.ReLU(),

29)

30defforward(self, x):

31x = F.relu(self.norm1(self.conv1(x)))# 卷积 BN ReLU

32x =self.pool(x)# 池化

33x = F.relu(self.norm2(self.conv2(x)))# 卷积 BN ReLU

34x = F.relu(self.norm3(self.conv3(x)))# 卷积 BN ReLU

35x =self.pool(x)

36x =self.convs(x)# 连续操作，里面是 conv -> BN -> ReLU -> conv -> BN -> ReLU

37x =self.pool(x)

38x = x.view(-1,128*8*8)# 将图像拉直为向量

39x =self.drop(x)

40x =self.out_layers(x)

41returnx

Note:

• 发表于:
• 原文链接：http://kuaibao.qq.com/s/20180425A1MJX800?refer=cp_1026
• 腾讯「云+社区」是腾讯内容开放平台帐号（企鹅号）传播渠道之一，根据《腾讯内容开放平台服务协议》转载发布内容。

2019-08-19

2019-08-19

2019-08-19

2018-04-18

2019-08-19

2019-08-19

2018-06-29

2018-04-28

2018-03-30

2019-08-19

2019-08-19

2019-08-19