Python2とpython3におけるpickle, print等の書式の違い

Python2で書かれたコードをPython3で走らせると、たいていの場合エラーが吐き出される。ネットで検索すると、無理にPython3を使わないで、Python2を使えというアドバイスが多い。というのも、パイソン初心者は、2と3の違いの修正に時間を取られるべきではないからで、3を学習したければ、3用に書かれた題材で学習すべきと言っている。ただ、良い教材が2で書かれているのも事実である。

ここから拾ったPython2.7コードをPython3.6で実行したら、例の如く、エラーが吐き出された。

 print "t=", t
^
SyntaxError: Missing parentheses in call to 'print'. Did you mean print("t=", t)?

Python3ではprintは()で括らないとダメらしく、何とも面倒くさい話である。printを()で括った後コードを実行したら、またエラーが吐き出された。python2と3の互換性はどうなっているのか。

11 from numpy import random
12
---> 13 import cPickle
14
15 import os

ModuleNotFoundError: No module named 'cPickle'

python3にはcPickleはないので、import pickle as cPickleを付け加えた。

77 b1 = tf.Variable(tf.random_normal([10], stddev=0.01))
78
---> 79 snapshot = cPickle.load(open("snapshot50.pkl"))
80 W0 = tf.Variable(snapshot["W0"])
81 b0 = tf.Variable(snapshot["b0"])

TypeError: a bytes-like object is required, not 'str'

データ・タイプをストリングからバイナリに変える必要があるらしいのでrbを加えた。

77 b1 = tf.Variable(tf.random_normal([10], stddev=0.01))
78
---> 79 snapshot = cPickle.load(open("snapshot50.pkl", 'rb'))
80 W0 = tf.Variable(snapshot["W0"])
81 b0 = tf.Variable(snapshot["b0"])

UnicodeDecodeError: 'ascii' codec can't decode byte 0x9b in position 1: ordinal not in range(128)

このコードが載っているサイトに、encoding="latin1"を付け加えればいいと書いてあったのでその通りにした。しかし、またまたまたエラーが吐き出された。

109 for i in range(5000):
110 #print i
--> 111 batch_xs, batch_ys = get_train_batch(M, 50)
112 sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})
113

37 for k in range(10):
38 train_size = len(M[train_k[k]])
---> 39 idx = array(random.permutation(train_size)[:n])
40 batch_xs = vstack((batch_xs, ((array(M[train_k[k]])[idx])/255.) ))
41 one_hot = zeros(10)

TypeError: slice indices must be integers or None or have an __index__ method

さすがに嫌になってきたが、これはn = N/10n = N//10に変えてやったらあっさり修正された。

126 snapshot["b0"] = sess.run(b0)
127 snapshot["b1"] = sess.run(b1)
--> 128 cPickle.dump(snapshot, open("new_snapshot"+str(i)+".pkl", "w"))

TypeError: write() argument must be str, not bytes

もう勘弁してくれと言いたくなるが、これは"w""wb"に変えることで修正された。

最終的に以下のように書き換えられたが、何とか無事コードを走らせることができた。

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
from pylab import *
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cbook as cbook
import time
from scipy.misc import imread
from scipy.misc import imresize
import matplotlib.image as mpimg
from scipy.ndimage import filters
import urllib
from numpy import random

import pickle as cPickle

import os
from scipy.io import loadmat

t = int(time.time())
#t = 1454219613
print ("t=", t)
random.seed(t)

M = loadmat("mnist_all.mat")

import tensorflow as tf

def get_train_batch(M, N):
n = N//10
batch_xs = zeros((0, 28*28))
batch_y_s = zeros( (0, 10))

train_k = ["train"+str(i) for i in range(10)]

train_size = len(M[train_k[0]])
#train_size = 5000

for k in range(10):
train_size = len(M[train_k[k]])
idx = array(random.permutation(train_size)[:n])
batch_xs = vstack((batch_xs, ((array(M[train_k[k]])[idx])/255.) ))
one_hot = zeros(10)
one_hot[k] = 1
batch_y_s = vstack((batch_y_s, tile(one_hot, (n, 1)) ))
return batch_xs, batch_y_s

def get_test(M):
batch_xs = zeros((0, 28*28))
batch_y_s = zeros( (0, 10))

test_k = ["test"+str(i) for i in range(10)]
for k in range(10):
batch_xs = vstack((batch_xs, ((array(M[test_k[k]])[:])/255.) ))
one_hot = zeros(10)
one_hot[k] = 1
batch_y_s = vstack((batch_y_s, tile(one_hot, (len(M[test_k[k]]), 1)) ))
return batch_xs, batch_y_s

def get_train(M):
batch_xs = zeros((0, 28*28))
batch_y_s = zeros( (0, 10))

train_k = ["train"+str(i) for i in range(10)]
for k in range(10):
batch_xs = vstack((batch_xs, ((array(M[train_k[k]])[:])/255.) ))
one_hot = zeros(10)
one_hot[k] = 1
batch_y_s = vstack((batch_y_s, tile(one_hot, (len(M[train_k[k]]), 1)) ))
return batch_xs, batch_y_s

x = tf.placeholder(tf.float32, [None, 784])

nhid = 300
W0 = tf.Variable(tf.random_normal([784, nhid], stddev=0.01))
b0 = tf.Variable(tf.random_normal([nhid], stddev=0.01))

W1 = tf.Variable(tf.random_normal([nhid, 10], stddev=0.01))
b1 = tf.Variable(tf.random_normal([10], stddev=0.01))

snapshot = cPickle.load(open("snapshot50.pkl", 'rb'), encoding="latin1")
W0 = tf.Variable(snapshot["W0"])
b0 = tf.Variable(snapshot["b0"])
W1 = tf.Variable(snapshot["W1"])
b1 = tf.Variable(snapshot["b1"])

layer1 = tf.nn.tanh(tf.matmul(x, W0)+b0)
layer2 = tf.matmul(layer1, W1)+b1

W = tf.Variable(tf.random_normal([784, 10], stddev=0.01))
b = tf.Variable(tf.random_normal([10], stddev=0.01))
layer = tf.matmul(x, W)+b

y = tf.nn.softmax(layer2)
y_ = tf.placeholder(tf.float32, [None, 10])

lam = 0.00000
decay_penalty =lam*tf.reduce_sum(tf.square(W0))+lam*tf.reduce_sum(tf.square(W1))
NLL = -tf.reduce_sum(y_*tf.log(y))+decay_penalty

train_step = tf.train.GradientDescentOptimizer(0.005).minimize(NLL)

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

correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
test_x, test_y = get_test(M)

for i in range(5000):
#print i
batch_xs, batch_ys = get_train_batch(M, 50)
sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})

if i % 1 == 0:
print ("i=",i)
print ("Test:", sess.run(accuracy, feed_dict={x: test_x, y_: test_y}))
batch_xs, batch_ys = get_train(M)

print ("Train:", sess.run(accuracy, feed_dict={x: batch_xs, y_: batch_ys}))
print ("Penalty:", sess.run(decay_penalty))

snapshot = {}
snapshot["W0"] = sess.run(W0)
snapshot["W1"] = sess.run(W1)
snapshot["b0"] = sess.run(b0)
snapshot["b1"] = sess.run(b1)
cPickle.dump(snapshot, open("new_snapshot"+str(i)+".pkl", "wb"))

英語の勉強のついでに、今後はpythonプログラミングも勉強していこうと思う。

スポンサーリンク