Commit | Line | Data |
---|---|---|
9fa4e985 JB |
1 | #!/usr/bin/env python3 |
2 | ||
3 | # -*- coding: utf-8 -*- | |
4 | import numpy as np | |
5 | from numpy.random import rand | |
6 | import pylab as pl | |
7 | ||
8 | ||
9 | def generateData(n): | |
10 | """ | |
11 | Generates a 2D linearly separable dataset with 2n samples. | |
12 | The third element of the sample is the label | |
13 | """ | |
14 | linear_offset = 0.6 | |
15 | xb = (rand(n) * 2 - 1) / 2 - linear_offset | |
16 | yb = (rand(n) * 2 - 1) / 2 + linear_offset | |
17 | xr = (rand(n) * 2 - 1) / 2 + linear_offset | |
18 | yr = (rand(n) * 2 - 1) / 2 - linear_offset | |
19 | inputs = [] | |
20 | for i in range(n): | |
21 | inputs.append([xb[i], yb[i], -1]) | |
22 | inputs.append([xr[i], yr[i], 1]) | |
23 | return inputs | |
24 | ||
25 | ||
26 | def generateData2(n): | |
27 | """ | |
28 | Generates a 2D linearly separable dataset with 2n samples. | |
29 | The third element of the sample is the label | |
30 | """ | |
31 | xb = (rand(n) * 2 - 1) / 2 + 0.5 | |
32 | yb = (rand(n) * 2 - 1) / 2 | |
33 | xr = (rand(n) * 2 - 1) / 2 + 1.5 | |
34 | yr = (rand(n) * 2 - 1) / 2 - 0.5 | |
35 | inputs = [] | |
36 | for i in range(n): | |
37 | inputs.append([xb[i], yb[i], -1]) | |
38 | inputs.append([xr[i], yr[i], 1]) | |
39 | return inputs | |
40 | ||
41 | ||
42 | def generateData3(n): | |
43 | """ | |
44 | Generates a 2D linearly separable dataset with about 2n samples. | |
45 | The third element of the sample is the label | |
46 | """ | |
47 | # (xb, yb) est dans le carré centré à l’origine de côté 1 | |
48 | xb = (rand(n) * 2 - 1) / 2 | |
49 | yb = (rand(n) * 2 - 1) / 2 | |
50 | # (xr, yr) est dans le carré centré à l’origine de côté 3 | |
51 | xr = 3 * (rand(4 * n) * 2 - 1) / 2 | |
52 | yr = 3 * (rand(4 * n) * 2 - 1) / 2 | |
53 | inputs = [] | |
54 | for i in range(n): | |
55 | inputs.append([xb[i], yb[i], -1]) | |
56 | for i in range(4 * n): | |
57 | # on ne conserve que les points extérieurs au carré centré à l’origine | |
58 | # de côté 2 | |
59 | if abs(xr[i]) >= 1 or abs(yr[i]) >= 1: | |
60 | inputs.append([xr[i], yr[i], 1]) | |
61 | return inputs | |
62 | ||
63 | ||
64 | def readData(file): | |
65 | f = open(file, "r") | |
66 | training_set = [] | |
67 | x = f.readline() | |
68 | while x: | |
69 | x_eval = eval(x) | |
70 | training_set.append([x_eval[0][0], x_eval[0][1], x_eval[1]]) | |
71 | x = f.readline() | |
72 | f.close() | |
73 | return training_set | |
74 | ||
75 | ||
76 | training_set_size = 150 | |
77 | # training_set = generateData3(training_set_size) | |
78 | training_set = readData("learn.data") | |
79 | data = np.array(training_set) | |
80 | X = data[:, 0:2] | |
81 | Y = data[:, -1] | |
82 | ||
83 | ||
84 | def perceptron_nobias(X, Y): | |
85 | w = np.zeros([len(X[0])]) | |
86 | # Go in the loop at least one time | |
87 | classification_error = 1 | |
88 | while not classification_error == 0: | |
89 | classification_error = 0 | |
90 | for x, y in zip(X, Y): | |
91 | if y * np.dot(w, x) <= 0: | |
92 | classification_error += 1 | |
93 | w = w + y * x | |
94 | print(classification_error) | |
95 | return w | |
96 | ||
97 | ||
98 | def complete(sample): | |
99 | new_sample = np.insert(sample, len(sample[0]), [1], axis=1) | |
100 | return np.array(new_sample) | |
101 | ||
102 | ||
103 | def plongement_phi(sample_element): | |
104 | return [1, sample_element[0], sample_element[1], sample_element[0]**2, | |
105 | sample_element[0] * sample_element[1], sample_element[1]**2] | |
106 | ||
107 | ||
108 | def apply_plongement(sample, p): | |
109 | output = [] | |
110 | for i in range(sample.shape[0]): | |
111 | current = p(sample[i]) | |
112 | output.append(current) | |
113 | return np.array(output) | |
114 | ||
115 | ||
116 | def f_from_k(coeffs, support_set, k, x): | |
117 | output = 0 | |
118 | for c, s in zip(coeffs, support_set): | |
119 | output += c * s[1] * k(s[0], x) | |
120 | return output | |
121 | ||
122 | ||
123 | def k1(X1, X2): | |
124 | return 1 + X1[0] * X2[0] + X1[1] * X2[1] + X1[0]**2 * X2[0]**2 \ | |
125 | + X1[0] * X1[1] * X2[0] * X2[1] + X1[1]**2 * X2[1]**2 | |
126 | ||
127 | ||
128 | def kg(x, y): | |
129 | # sigma = 20 # do not converge | |
130 | # sigma = 10 # do not converge | |
131 | sigma = 1 # overfitting | |
132 | # sigma = 0.5 # overfitting | |
133 | # sigma = 0.2 # overfitting | |
134 | return np.exp(-((x[0] - y[0])**2 + (x[1] - y[1])**2) / sigma**2) | |
135 | ||
136 | ||
137 | def perceptron_k(X, Y, k): | |
138 | coeffs = [] | |
139 | support_set = [] | |
140 | # Go in the loop at least one time | |
141 | classification_error = 1 | |
142 | while not classification_error == 0: | |
143 | classification_error = 0 | |
144 | for x, y in zip(X, Y): | |
145 | if y * f_from_k(coeffs, support_set, k, x) <= 0: | |
146 | if x not in support_set: | |
147 | support_set.append((x, y)) | |
148 | coeffs.append(1) | |
149 | else: | |
150 | coeffs[support_set.index((x, y))] += 1 | |
151 | classification_error += 1 | |
152 | print(classification_error) | |
153 | return np.array(coeffs), np.array(support_set) | |
154 | ||
155 | ||
156 | def f(w, x, y): | |
157 | return w[0] + w[1] * x + w[2] * y + w[3] * x**2 + w[4] * x * y + w[5] * y**2 | |
158 | ||
159 | ||
160 | pl.scatter(X[:, 0], X[:, 1], c=Y) | |
161 | pl.title(u"Perceptron - prolontaged hyperplan") | |
162 | ||
163 | # k = k1 | |
164 | # coeffs, support_set = perceptron_k(X, Y, k) | |
165 | k = kg | |
166 | coeffs, support_set = perceptron_k(X, Y, k) | |
167 | res = training_set_size | |
168 | for x in range(res): | |
169 | for y in range(res): | |
170 | if abs(f_from_k(coeffs, support_set, k, [-3 / 2 + 3 * x / res, -3 / 2 + 3 * y / res])) < 0.01: | |
171 | pl.plot(-3 / 2 + 3 * x / res, -3 / 2 + 3 * y / res, 'xr') | |
172 | ||
173 | # X = apply_plongement(X, plongement_phi) | |
174 | # w = perceptron_nobias(X, Y) | |
175 | # for x in range(res): | |
176 | # for y in range(res): | |
177 | # if abs(f(w, -3 / 2 + 3 * x / res, -3 / 2 + 3 * y / res)) < 0.01: | |
178 | # pl.plot(-3 / 2 + 3 * x / res, -3 / 2 + 3 * y / res, 'xb') | |
179 | ||
180 | pl.show() |