Spaces:
Runtime error
Runtime error
boda
commited on
Commit
·
d7e4f1f
1
Parent(s):
bfb0af7
add MLP models
Browse files- app.py +36 -0
- model/__pycache__/generate.cpython-310.pyc +0 -0
- model/__pycache__/layers.cpython-310.pyc +0 -0
- model/generate.py +118 -0
- model/layers.py +111 -0
- model/weights/ar_dataset_weights.pt +0 -0
- model/weights/en_dataset_weights.pt +0 -0
- requirmenets.txt +1 -0
app.py
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
from model.generate import generate_names
|
3 |
+
|
4 |
+
col1, col2, col3 = st.columns([1,1,1])
|
5 |
+
|
6 |
+
|
7 |
+
st.markdown('''This is a simple MLP that predicts the next character given the context of the previous 5 characters!
|
8 |
+
If you want to play with this, see the repo [here](https://github.com/BodaSadalla98/Arabic_makemore)
|
9 |
+
|
10 |
+
|
11 |
+
|
12 |
+
''')
|
13 |
+
|
14 |
+
option = col2.selectbox(
|
15 |
+
'Select the language to generate the names with:',
|
16 |
+
('Arabic', 'English'))
|
17 |
+
number = col2.number_input(label='Enter how many names to generate..', min_value=0, max_value=1000, value=5)
|
18 |
+
|
19 |
+
names = ''
|
20 |
+
if col2.button('Generate'):
|
21 |
+
if option =='English':
|
22 |
+
names = generate_names(number,'en')
|
23 |
+
else:
|
24 |
+
names = generate_names(number,'ar')
|
25 |
+
|
26 |
+
|
27 |
+
for name in names:
|
28 |
+
new_title = f'<p style="font-family:sans-serif;text-align: center; color:Purple; font-size: 30px;">{name}</p>'
|
29 |
+
col2.markdown(new_title, unsafe_allow_html=True)
|
30 |
+
|
31 |
+
|
32 |
+
st.markdown('''
|
33 |
+
If you have any questions, contact me: **@bodasadallah**
|
34 |
+
''')
|
35 |
+
# st.write(names)
|
36 |
+
|
model/__pycache__/generate.cpython-310.pyc
ADDED
Binary file (3.22 kB). View file
|
|
model/__pycache__/layers.cpython-310.pyc
ADDED
Binary file (3.74 kB). View file
|
|
model/generate.py
ADDED
@@ -0,0 +1,118 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import torch
|
2 |
+
from model.layers import *
|
3 |
+
# from layers import *
|
4 |
+
|
5 |
+
import pathlib
|
6 |
+
from pathlib import Path
|
7 |
+
|
8 |
+
|
9 |
+
CONTEXT_SIZE = 5
|
10 |
+
n_hidden = 100
|
11 |
+
n_embed = 10
|
12 |
+
EN_VOCAB_SIZE = 27
|
13 |
+
AR_VOCAB_SIZE = 37
|
14 |
+
ACTIVATION = 'relu'
|
15 |
+
|
16 |
+
ar_itos = {0: '.', 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: 'ي'}
|
17 |
+
en_itos= {0: '.', 1: '-', 2: 'a', 3: 'b', 4: 'c', 5: 'd', 6: 'e', 7: 'f', 8: 'g', 9: 'h', 10: 'i', 11: 'j', 12: 'k', 13: 'l', 14: 'm', 15: 'n', 16: 'o', 17: 'p', 18: 'q', 19: 'r', 20: 's', 21: 't', 22: 'u', 23: 'v', 24: 'w', 25: 'y', 26: 'z'}
|
18 |
+
arabic_layers = [
|
19 |
+
Linear(CONTEXT_SIZE*n_embed , n_hidden),BatchNorm(n_hidden), Activation(ACTIVATION),
|
20 |
+
Linear(n_hidden, n_hidden),BatchNorm(n_hidden), Activation(ACTIVATION),
|
21 |
+
Linear(n_hidden, n_hidden),BatchNorm(n_hidden), Activation(ACTIVATION),
|
22 |
+
Linear(n_hidden , AR_VOCAB_SIZE)
|
23 |
+
]
|
24 |
+
|
25 |
+
english_layers = [
|
26 |
+
Linear(CONTEXT_SIZE*n_embed , n_hidden),BatchNorm(n_hidden), Activation(ACTIVATION),
|
27 |
+
Linear(n_hidden, n_hidden),BatchNorm(n_hidden), Activation(ACTIVATION),
|
28 |
+
Linear(n_hidden, n_hidden),BatchNorm(n_hidden), Activation(ACTIVATION),
|
29 |
+
Linear(n_hidden , EN_VOCAB_SIZE)
|
30 |
+
]
|
31 |
+
|
32 |
+
|
33 |
+
|
34 |
+
parent_path = Path(__file__).parent
|
35 |
+
arabic_dict = torch.load(Path.joinpath(parent_path,'weights/ar_dataset_weights.pt'))
|
36 |
+
english_dict= torch.load(Path.joinpath(parent_path,'weights/en_dataset_weights.pt'))
|
37 |
+
|
38 |
+
## Weights
|
39 |
+
arabic_params = arabic_dict['params']
|
40 |
+
english_params = english_dict['params']
|
41 |
+
|
42 |
+
## Batch norm means ans stds
|
43 |
+
arabic_bn_conf = arabic_dict['bn_conf']
|
44 |
+
english_bn_conf = english_dict['bn_conf']
|
45 |
+
|
46 |
+
|
47 |
+
# Load embeddings
|
48 |
+
arabic_embedding = arabic_params[0]
|
49 |
+
english_embedding = english_params[0]
|
50 |
+
|
51 |
+
## Load weights
|
52 |
+
j = 0
|
53 |
+
for i,l in enumerate(arabic_layers):
|
54 |
+
l.set_parameters( arabic_params[i+1] )
|
55 |
+
if l.__class__.__name__ == "BatchNorm":
|
56 |
+
l.set_mean_std(arabic_bn_conf[j])
|
57 |
+
j+=1
|
58 |
+
|
59 |
+
j = 0
|
60 |
+
for i,l in enumerate(english_layers):
|
61 |
+
l.set_parameters( english_params[i+1] )
|
62 |
+
if l.__class__.__name__ == "BatchNorm":
|
63 |
+
l.set_mean_std(english_bn_conf[j])
|
64 |
+
j+=1
|
65 |
+
|
66 |
+
def forward(x_batch, is_training,lang):
|
67 |
+
|
68 |
+
if lang =='ar':
|
69 |
+
embedding = arabic_embedding
|
70 |
+
layers = arabic_layers
|
71 |
+
|
72 |
+
elif lang =='en':
|
73 |
+
embedding = english_embedding
|
74 |
+
layers = english_layers
|
75 |
+
|
76 |
+
|
77 |
+
x_batch = embedding[x_batch]
|
78 |
+
x = x_batch.view(x_batch.shape[0], -1)
|
79 |
+
for layer in layers:
|
80 |
+
x = layer(x, is_training)
|
81 |
+
return x
|
82 |
+
|
83 |
+
|
84 |
+
def generate_name(lang):
|
85 |
+
|
86 |
+
w = ''
|
87 |
+
last_ch = [0]* CONTEXT_SIZE
|
88 |
+
while True:
|
89 |
+
last_ch = torch.tensor(last_ch).unsqueeze(0)
|
90 |
+
|
91 |
+
|
92 |
+
x = forward(last_ch, False, lang)
|
93 |
+
p = torch.softmax(x, dim=1)
|
94 |
+
next_ch = torch.multinomial(p, num_samples=1, replacement=True).item()
|
95 |
+
if lang =='ar':
|
96 |
+
w += ar_itos[next_ch]
|
97 |
+
elif lang == 'en':
|
98 |
+
w += en_itos[next_ch]
|
99 |
+
|
100 |
+
last_ch = last_ch.clone().detach().squeeze(0)
|
101 |
+
last_ch = last_ch.tolist()
|
102 |
+
last_ch = last_ch[1:] + [next_ch]
|
103 |
+
if next_ch == 0:
|
104 |
+
break
|
105 |
+
|
106 |
+
return w[:-1]
|
107 |
+
|
108 |
+
def generate_names(n,lang):
|
109 |
+
ret = []
|
110 |
+
for i in range(n):
|
111 |
+
ret.append(generate_name(lang))
|
112 |
+
|
113 |
+
return ret
|
114 |
+
|
115 |
+
|
116 |
+
if __name__ == '__main__':
|
117 |
+
|
118 |
+
pass
|
model/layers.py
ADDED
@@ -0,0 +1,111 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import torch
|
2 |
+
|
3 |
+
|
4 |
+
|
5 |
+
class Linear():
|
6 |
+
def __init__(self, in_n, out_n, bias=True) -> None:
|
7 |
+
self.params = []
|
8 |
+
self.have_bias = bias
|
9 |
+
self.weight = torch.randn((in_n,out_n)) / (in_n**0.5)
|
10 |
+
self.params.append(self.weight)
|
11 |
+
|
12 |
+
self.bias = None
|
13 |
+
if self.have_bias:
|
14 |
+
self.bias = torch.zeros(out_n)
|
15 |
+
self.params.append(self.bias)
|
16 |
+
|
17 |
+
def __call__(self,x, is_training =True):
|
18 |
+
self.is_training = is_training
|
19 |
+
|
20 |
+
self.out = x @ self.params[0]
|
21 |
+
if self.have_bias:
|
22 |
+
self.out += self.params[1]
|
23 |
+
return self.out
|
24 |
+
|
25 |
+
def set_parameters(self,p):
|
26 |
+
self.params = p
|
27 |
+
# self.weight = p[0]
|
28 |
+
# self.bias = p[1]
|
29 |
+
# self.params = [p]
|
30 |
+
|
31 |
+
def parameters(self):
|
32 |
+
return self.params
|
33 |
+
|
34 |
+
|
35 |
+
class BatchNorm():
|
36 |
+
def __init__(self, in_n,eps=1e-5, momentum = 0.1) -> None:
|
37 |
+
self.eps = eps
|
38 |
+
self.is_training = True
|
39 |
+
self.momentum = momentum
|
40 |
+
self.running_mean = torch.zeros(in_n)
|
41 |
+
self.running_std = torch.ones(in_n)
|
42 |
+
self.gain = torch.ones(in_n)
|
43 |
+
self.bias = torch.zeros(in_n)
|
44 |
+
self.params = [self.gain , self.bias]
|
45 |
+
|
46 |
+
|
47 |
+
def __call__(self, x, is_training= True):
|
48 |
+
|
49 |
+
self.is_training = is_training
|
50 |
+
if self.is_training:
|
51 |
+
mean = x.mean(0,keepdims= True)
|
52 |
+
## unbiased??
|
53 |
+
std = x.std(0,keepdims= True)
|
54 |
+
|
55 |
+
self.out = self.params[0] * (x - mean / (std + self.eps**0.5)) + self.params[1]
|
56 |
+
|
57 |
+
with torch.no_grad():
|
58 |
+
self.running_mean = self.running_mean * (1- self.momentum) \
|
59 |
+
+ self.momentum * mean
|
60 |
+
self.running_std = self.running_std * (1- self.momentum) \
|
61 |
+
+ self.momentum * std
|
62 |
+
|
63 |
+
else:
|
64 |
+
# print(self.running_mean , self.running_std)
|
65 |
+
self.out = self.params[0] * (x - self.running_mean / (self.running_std + self.eps**0.5)) + self.params[1]
|
66 |
+
|
67 |
+
|
68 |
+
|
69 |
+
return self.out
|
70 |
+
|
71 |
+
def set_parameters(self,p):
|
72 |
+
self.params = p
|
73 |
+
# self.gain = p[0]
|
74 |
+
# self.bias = p[1]
|
75 |
+
# self.params = [self.gain , self.bias]
|
76 |
+
def set_mean_std(self, conf):
|
77 |
+
self.running_mean = conf[0]
|
78 |
+
self.running_std = conf[1]
|
79 |
+
def get_mean_std(self):
|
80 |
+
return [self.running_mean, self.running_std]
|
81 |
+
|
82 |
+
def parameters(self):
|
83 |
+
return self.params
|
84 |
+
|
85 |
+
class Activation():
|
86 |
+
def __init__(self, activation='tanh'):
|
87 |
+
self.params = []
|
88 |
+
if activation == 'tanh':
|
89 |
+
self.forward = self._forward_tanh
|
90 |
+
elif activation == 'relu':
|
91 |
+
self.forward = self._forward_relu
|
92 |
+
else:
|
93 |
+
raise Exception('Only tanh, and relu activations are supported')
|
94 |
+
|
95 |
+
def _forward_relu(self,x):
|
96 |
+
return torch.relu(x)
|
97 |
+
def _forward_tanh(self,x):
|
98 |
+
return torch.tanh(x)
|
99 |
+
|
100 |
+
def __call__(self, x, is_training= True):
|
101 |
+
|
102 |
+
self.is_training = is_training
|
103 |
+
|
104 |
+
|
105 |
+
self.out = self.forward(x)
|
106 |
+
return self.out
|
107 |
+
|
108 |
+
def set_parameters(self,p):
|
109 |
+
self.params = p
|
110 |
+
def parameters(self):
|
111 |
+
return self.params
|
model/weights/ar_dataset_weights.pt
ADDED
Binary file (128 kB). View file
|
|
model/weights/en_dataset_weights.pt
ADDED
Binary file (123 kB). View file
|
|
requirmenets.txt
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
torch
|