Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit fabe335

Browse files
Mark Poscablo9prady9
Mark Poscablo
authored andcommitted
Added logistic regression example
1 parent 834dc14 commit fabe335

File tree

3 files changed

+370
-0
lines changed

3 files changed

+370
-0
lines changed

‎examples/common/idxio.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#!/usr/bin/python
2+
3+
#######################################################
4+
# Copyright (c) 2019, ArrayFire
5+
# All rights reserved.
6+
#
7+
# This file is distributed under 3-clause BSD license.
8+
# The complete license agreement can be obtained at:
9+
# http://arrayfire.com/licenses/BSD-3-Clause
10+
########################################################
11+
12+
def reverse_char(b):
13+
b = (b & 0xF0) >> 4 | (b & 0x0F) << 4
14+
b = (b & 0xCC) >> 2 | (b & 0x33) << 2
15+
b = (b & 0xAA) >> 1 | (b & 0x55) << 1
16+
return b
17+
18+
19+
# http://stackoverflow.com/a/9144870/2192361
20+
def reverse(x):
21+
x = ((x >> 1) & 0x55555555) | ((x & 0x55555555) << 1)
22+
x = ((x >> 2) & 0x33333333) | ((x & 0x33333333) << 2)
23+
x = ((x >> 4) & 0x0f0f0f0f) | ((x & 0x0f0f0f0f) << 4)
24+
x = ((x >> 8) & 0x00ff00ff) | ((x & 0x00ff00ff) << 8)
25+
x = ((x >> 16) & 0xffff) | ((x & 0xffff) << 16);
26+
return x
27+
28+
29+
def read_idx(name):
30+
with open(name, 'rb') as f:
31+
# In the C++ version, bytes the size of 4 chars are being read
32+
# May not work properly in machines where a char is not 1 byte
33+
bytes_read = f.read(4)
34+
bytes_read = bytearray(bytes_read)
35+
36+
if bytes_read[2] != 8:
37+
raise RuntimeError('Unsupported data type')
38+
39+
numdims = bytes_read[3]
40+
elemsize = 1
41+
42+
# Read the dimensions
43+
elem = 1
44+
dims = [0] * numdims
45+
for i in range(numdims):
46+
bytes_read = bytearray(f.read(4))
47+
48+
# Big endian to little endian
49+
for j in range(4):
50+
bytes_read[j] = reverse_char(bytes_read[j])
51+
bytes_read_int = int.from_bytes(bytes_read, 'little')
52+
dim = reverse(bytes_read_int)
53+
54+
elem = elem * dim;
55+
dims[i] = dim;
56+
57+
# Read the data
58+
cdata = f.read(elem * elemsize)
59+
cdata = list(cdata)
60+
data = [float(cdata_elem) for cdata_elem in cdata]
61+
62+
return (dims, data)
63+
64+
Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
#!/usr/bin/python
2+
3+
#######################################################
4+
# Copyright (c) 2019, ArrayFire
5+
# All rights reserved.
6+
#
7+
# This file is distributed under 3-clause BSD license.
8+
# The complete license agreement can be obtained at:
9+
# http://arrayfire.com/licenses/BSD-3-Clause
10+
########################################################
11+
12+
from mnist_common import display_results, setup_mnist
13+
14+
import sys
15+
import time
16+
17+
import arrayfire as af
18+
from arrayfire.algorithm import max, imax, count, sum
19+
from arrayfire.arith import abs, sigmoid, log
20+
from arrayfire.array import transpose
21+
from arrayfire.blas import matmul, matmulTN
22+
from arrayfire.data import constant, join, lookup, moddims
23+
from arrayfire.device import set_device, sync, eval
24+
25+
26+
def accuracy(predicted, target):
27+
_, tlabels = af.imax(target, 1)
28+
_, plabels = af.imax(predicted, 1)
29+
return 100 * af.count(plabels == tlabels) / tlabels.elements()
30+
31+
32+
def abserr(predicted, target):
33+
return 100 * af.sum(af.abs(predicted - target)) / predicted.elements()
34+
35+
36+
# Predict (probability) based on given parameters
37+
def predict_proba(X, Weights):
38+
Z = af.matmul(X, Weights)
39+
return af.sigmoid(Z)
40+
41+
42+
# Predict (log probability) based on given parameters
43+
def predict_log_proba(X, Weights):
44+
return af.log(predict_proba(X, Weights))
45+
46+
47+
# Give most likely class based on given parameters
48+
def predict(X, Weights):
49+
probs = predict_proba(X, Weights)
50+
_, classes = af.imax(probs, 1)
51+
return classes
52+
53+
54+
def cost(Weights, X, Y, lambda_param=1.0):
55+
# Number of samples
56+
m = Y.dims()[0]
57+
58+
dim0 = Weights.dims()[0]
59+
dim1 = Weights.dims()[1] if len(Weights.dims()) > 1 else None
60+
dim2 = Weights.dims()[2] if len(Weights.dims()) > 2 else None
61+
dim3 = Weights.dims()[3] if len(Weights.dims()) > 3 else None
62+
# Make the lambda corresponding to Weights(0) == 0
63+
lambdat = af.constant(lambda_param, dim0, dim1, dim2, dim3)
64+
65+
# No regularization for bias weights
66+
lambdat[0, :] = 0
67+
68+
# Get the prediction
69+
H = predict_proba(X, Weights)
70+
71+
# Cost of misprediction
72+
Jerr = -1 * af.sum(Y * af.log(H) + (1 - Y) * af.log(1 - H), dim=0)
73+
74+
# Regularization cost
75+
Jreg = 0.5 * af.sum(lambdat * Weights * Weights, dim=0)
76+
77+
# Total cost
78+
J = (Jerr + Jreg) / m
79+
80+
# Find the gradient of cost
81+
D = (H - Y)
82+
dJ = (af.matmulTN(X, D) + lambdat * Weights) / m
83+
84+
return J, dJ
85+
86+
87+
def train(X, Y, alpha=0.1, lambda_param=1.0, maxerr=0.01, maxiter=1000, verbose=False):
88+
# Initialize parameters to 0
89+
Weights = af.constant(0, X.dims()[1], Y.dims()[1])
90+
91+
for i in range(maxiter):
92+
# Get the cost and gradient
93+
J, dJ = cost(Weights, X, Y, lambda_param)
94+
95+
err = af.max(af.abs(J))
96+
if err < maxerr:
97+
print('Iteration {0:4d} Err: {1:4f}'.format(i + 1, err))
98+
print('Training converged')
99+
return Weights
100+
101+
if verbose and ((i+1) % 10 == 0):
102+
print('Iteration {0:4d} Err: {1:4f}'.format(i + 1, err))
103+
104+
# Update the parameters via gradient descent
105+
Weights = Weights - alpha * dJ
106+
107+
if verbose:
108+
print('Training stopped after {0:d} iterations'.format(maxiter))
109+
110+
return Weights
111+
112+
113+
def benchmark_logistic_regression(train_feats, train_targets, test_feats):
114+
t0 = time.time()
115+
Weights = train(train_feats, train_targets, 0.1, 1.0, 0.01, 1000)
116+
af.eval(Weights)
117+
sync()
118+
t1 = time.time()
119+
dt = t1 - t0
120+
print('Training time: {0:4.4f} s'.format(dt))
121+
122+
t0 = time.time()
123+
iters = 100
124+
for i in range(iters):
125+
test_outputs = predict(test_feats, Weights)
126+
af.eval(test_outputs)
127+
sync()
128+
t1 = time.time()
129+
dt = t1 - t0
130+
print('Prediction time: {0:4.4f} s'.format(dt / iters))
131+
132+
133+
# Demo of one vs all logistic regression
134+
def logit_demo(console, perc):
135+
# Load mnist data
136+
frac = float(perc) / 100.0
137+
mnist_data = setup_mnist(frac, True)
138+
num_classes = mnist_data[0]
139+
num_train = mnist_data[1]
140+
num_test = mnist_data[2]
141+
train_images = mnist_data[3]
142+
test_images = mnist_data[4]
143+
train_targets = mnist_data[5]
144+
test_targets = mnist_data[6]
145+
146+
# Reshape images into feature vectors
147+
feature_length = int(train_images.elements() / num_train);
148+
train_feats = af.transpose(af.moddims(train_images, feature_length, num_train))
149+
test_feats = af.transpose(af.moddims(test_images, feature_length, num_test))
150+
151+
train_targets = af.transpose(train_targets)
152+
test_targets = af.transpose(test_targets)
153+
154+
num_train = train_feats.dims()[0]
155+
num_test = test_feats.dims()[0]
156+
157+
# Add a bias that is always 1
158+
train_bias = af.constant(1, num_train, 1)
159+
test_bias = af.constant(1, num_test, 1)
160+
train_feats = af.join(1, train_bias, train_feats)
161+
test_feats = af.join(1, test_bias, test_feats)
162+
163+
# Train logistic regression parameters
164+
Weights = train(train_feats, train_targets,
165+
0.1, # learning rate
166+
1.0, # regularization constant
167+
0.01, # max error
168+
1000, # max iters
169+
True # verbose mode
170+
)
171+
af.eval(Weights)
172+
af.sync()
173+
174+
# Predict the results
175+
train_outputs = predict_proba(train_feats, Weights)
176+
test_outputs = predict_proba(test_feats, Weights)
177+
178+
print('Accuracy on training data: {0:2.2f}'.format(accuracy(train_outputs, train_targets)))
179+
print('Accuracy on testing data: {0:2.2f}'.format(accuracy(test_outputs, test_targets)))
180+
print('Maximum error on testing data: {0:2.2f}'.format(abserr(test_outputs, test_targets)))
181+
182+
benchmark_logistic_regression(train_feats, train_targets, test_feats)
183+
184+
if not console:
185+
test_outputs = af.transpose(test_outputs)
186+
# Get 20 random test images
187+
display_results(test_images, test_outputs, af.transpose(test_targets), 20, True)
188+
189+
def main():
190+
argc = len(sys.argv)
191+
192+
device = int(sys.argv[1]) if argc > 1 else 0
193+
console = sys.argv[2][0] == '-' if argc > 2 else False
194+
perc = int(sys.argv[3]) if argc > 3 else 60
195+
196+
try:
197+
af.set_device(device)
198+
af.info()
199+
logit_demo(console, perc)
200+
except Exception as e:
201+
print('Error: ', str(e))
202+
203+
204+
if __name__ == '__main__':
205+
main()
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
#!/usr/bin/python
2+
3+
#######################################################
4+
# Copyright (c) 2019, ArrayFire
5+
# All rights reserved.
6+
#
7+
# This file is distributed under 3-clause BSD license.
8+
# The complete license agreement can be obtained at:
9+
# http://arrayfire.com/licenses/BSD-3-Clause
10+
########################################################
11+
12+
import sys
13+
sys.path.insert(0, '../common')
14+
from idxio import read_idx
15+
16+
import arrayfire as af
17+
from arrayfire.algorithm import where
18+
from arrayfire.array import Array
19+
from arrayfire.data import constant, lookup, moddims
20+
from arrayfire.random import randu
21+
22+
23+
def classify(arr, k, expand_labels):
24+
ret_str = ''
25+
if expand_labels:
26+
vec = arr[:, k].as_type(af.Dtype.f32)
27+
h_vec = vec.to_list()
28+
data = []
29+
30+
for i in range(vec.elements()):
31+
data.append((h_vec[i], i))
32+
33+
data = sorted(data, key=lambda pair: pair[0], reverse=True)
34+
35+
ret_str = str(data[0][1])
36+
37+
else:
38+
ret_str = str(int(arr[k].as_type(af.Dtype.f32).scalar()))
39+
40+
return ret_str
41+
42+
43+
def setup_mnist(frac, expand_labels):
44+
idims, idata = read_idx('../../assets/examples/data/mnist/images-subset')
45+
ldims, ldata = read_idx('../../assets/examples/data/mnist/labels-subset')
46+
47+
idims.reverse()
48+
numdims = len(idims)
49+
images = af.Array(idata, tuple(idims))
50+
51+
R = af.randu(10000, 1);
52+
cond = R < min(frac, 0.8)
53+
train_indices = af.where(cond)
54+
test_indices = af.where(~cond)
55+
56+
train_images = af.lookup(images, train_indices, 2) / 255
57+
test_images = af.lookup(images, test_indices, 2) / 255
58+
59+
num_classes = 10
60+
num_train = train_images.dims()[2]
61+
num_test = test_images.dims()[2]
62+
63+
if expand_labels:
64+
train_labels = af.constant(0, num_classes, num_train)
65+
test_labels = af.constant(0, num_classes, num_test)
66+
67+
h_train_idx = train_indices.to_list()
68+
h_test_idx = test_indices.to_list()
69+
70+
for i in range(num_train):
71+
train_labels[ldata[h_train_idx[i]], i] = 1
72+
73+
for i in range(num_test):
74+
test_labels[ldata[h_test_idx[i]], i] = 1
75+
76+
else:
77+
labels = af.Array(ldata, tuple(ldims))
78+
train_labels = labels[train_indices]
79+
test_labels = labels[test_indices]
80+
81+
return (num_classes,
82+
num_train,
83+
num_test,
84+
train_images,
85+
test_images,
86+
train_labels,
87+
test_labels)
88+
89+
90+
def display_results(test_images, test_output, test_actual, num_display, expand_labels):
91+
for i in range(num_display):
92+
print('Predicted: ', classify(test_output, i, expand_labels))
93+
print('Actual: ', classify(test_actual, i, expand_labels))
94+
95+
img = (test_images[:, :, i] > 0.1).as_type(af.Dtype.u8)
96+
img = af.moddims(img, img.elements()).to_list()
97+
for j in range(28):
98+
for k in range(28):
99+
print('\u2588' if img[j * 28 + k] > 0 else ' ', end='')
100+
print()
101+
input()

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /