pytensorforge 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (146) hide show
  1. cli.py +604 -0
  2. pytensorforge-0.1.0.dist-info/METADATA +103 -0
  3. pytensorforge-0.1.0.dist-info/RECORD +146 -0
  4. pytensorforge-0.1.0.dist-info/WHEEL +5 -0
  5. pytensorforge-0.1.0.dist-info/entry_points.txt +2 -0
  6. pytensorforge-0.1.0.dist-info/top_level.txt +2 -0
  7. src/__init__.py +0 -0
  8. src/activations/Activation.py +4 -0
  9. src/activations/ELU.py +11 -0
  10. src/activations/GELU.py +6 -0
  11. src/activations/ReLU.py +27 -0
  12. src/activations/SELU.py +14 -0
  13. src/activations/Sigmoid.py +27 -0
  14. src/activations/Softmax.py +84 -0
  15. src/activations/Tanh.py +29 -0
  16. src/activations/__init__.py +17 -0
  17. src/config.py +120 -0
  18. src/core/Matrix.py +3 -0
  19. src/core/Scalar.py +18 -0
  20. src/core/Tensor.py +866 -0
  21. src/core/Vector.py +31 -0
  22. src/core/__init__.py +0 -0
  23. src/data/__init__.py +0 -0
  24. src/data/chat_dataset.py +188 -0
  25. src/data/corpus.py +104 -0
  26. src/data/document_stream.py +178 -0
  27. src/data/parallel_encode.py +86 -0
  28. src/data/prefetch.py +62 -0
  29. src/data/shard_builder.py +119 -0
  30. src/data/shard_writer.py +81 -0
  31. src/data/sharded_dataset.py +112 -0
  32. src/data/streaming_dataset.py +132 -0
  33. src/data/validation.py +212 -0
  34. src/inference/__init__.py +0 -0
  35. src/inference/chat_template.py +384 -0
  36. src/inference/config.py +48 -0
  37. src/inference/engine.py +241 -0
  38. src/inference/export.py +133 -0
  39. src/inference/kv_cache.py +65 -0
  40. src/inference/runtime.py +161 -0
  41. src/inference/sampling.py +42 -0
  42. src/inference/scheduler.py +473 -0
  43. src/inference/text.py +67 -0
  44. src/initializers/Constant.py +9 -0
  45. src/initializers/GlorotNormal.py +15 -0
  46. src/initializers/GlorotUniform.py +26 -0
  47. src/initializers/HeNormal.py +15 -0
  48. src/initializers/HeUniform.py +14 -0
  49. src/initializers/Initializer.py +4 -0
  50. src/initializers/LecunNormal.py +16 -0
  51. src/initializers/LecunUniform.py +14 -0
  52. src/initializers/Ones.py +6 -0
  53. src/initializers/Orthogonal.py +14 -0
  54. src/initializers/RandomNormal.py +14 -0
  55. src/initializers/RandomUniform.py +14 -0
  56. src/initializers/Zeros.py +8 -0
  57. src/initializers/__init__.py +17 -0
  58. src/loss/CategoricalCrossEntropy.py +9 -0
  59. src/loss/CrossEntropyLoss.py +34 -0
  60. src/loss/CrossEntropyWithLogitsLoss.py +59 -0
  61. src/loss/Hinge.py +5 -0
  62. src/loss/Huber.py +22 -0
  63. src/loss/Loss.py +6 -0
  64. src/loss/MSE.py +7 -0
  65. src/loss/MSELoss.py +10 -0
  66. src/loss/SparseCategoricalCrossEntropy.py +15 -0
  67. src/loss/__init__.py +18 -0
  68. src/loss/bce.py +34 -0
  69. src/loss/mae.py +16 -0
  70. src/math/__init__.py +0 -0
  71. src/math/clip.py +37 -0
  72. src/math/exp.py +27 -0
  73. src/math/log.py +25 -0
  74. src/math/sigmoid.py +5 -0
  75. src/models/__init__.py +0 -0
  76. src/models/embedding/Embedding.py +65 -0
  77. src/models/embedding/__init__.py +0 -0
  78. src/models/gpt/__init__.py +0 -0
  79. src/models/gpt/attention.py +158 -0
  80. src/models/gpt/block.py +74 -0
  81. src/models/gpt/config.py +103 -0
  82. src/models/gpt/context.py +44 -0
  83. src/models/gpt/model.py +165 -0
  84. src/models/gpt/recompute.py +35 -0
  85. src/models/gpt/rope.py +84 -0
  86. src/models/regression/Linear.py +51 -0
  87. src/models/regression/Logistic.py +36 -0
  88. src/models/regression/__init__.py +0 -0
  89. src/models/seq/Sequential.py +297 -0
  90. src/models/seq/__init__.py +0 -0
  91. src/models/svm/__init__.py +0 -0
  92. src/models/tokenizer/BPETokenizer.py +228 -0
  93. src/models/tokenizer/__init__.py +0 -0
  94. src/models/transformers/Dropout.py +35 -0
  95. src/models/transformers/LastToken.py +10 -0
  96. src/models/transformers/LayerNorm.py +54 -0
  97. src/models/transformers/Linear.py +18 -0
  98. src/models/transformers/MultiHeadAttention.py +130 -0
  99. src/models/transformers/TransformerBlock.py +79 -0
  100. src/models/transformers/__init__.py +0 -0
  101. src/neural/Dense.py +58 -0
  102. src/neural/LSTM.py +167 -0
  103. src/neural/Layer.py +72 -0
  104. src/neural/Parameter.py +30 -0
  105. src/neural/RNN.py +83 -0
  106. src/neural/__init__.py +0 -0
  107. src/ops/__init__.py +0 -0
  108. src/ops/stack.py +40 -0
  109. src/optimizers/Adagrad.py +31 -0
  110. src/optimizers/Adam.py +98 -0
  111. src/optimizers/AdamW.py +84 -0
  112. src/optimizers/Batch.py +11 -0
  113. src/optimizers/Nesterov.py +35 -0
  114. src/optimizers/Optimizer.py +18 -0
  115. src/optimizers/RMSProp.py +35 -0
  116. src/optimizers/SGD.py +30 -0
  117. src/optimizers/SGDMomentum.py +28 -0
  118. src/optimizers/__init__.py +9 -0
  119. src/scaling/StandardScaler.py +15 -0
  120. src/scaling/__init__.py +0 -0
  121. src/serialization/__init__.py +0 -0
  122. src/serialization/checkpoint.py +58 -0
  123. src/serialization/modelio.py +132 -0
  124. src/serving/__init__.py +0 -0
  125. src/serving/app.py +792 -0
  126. src/serving/config.py +216 -0
  127. src/serving/errors.py +51 -0
  128. src/serving/http.py +599 -0
  129. src/serving/metrics.py +293 -0
  130. src/serving/model_server.py +287 -0
  131. src/serving/protocol.py +377 -0
  132. src/serving/security.py +200 -0
  133. src/serving/server.py +121 -0
  134. src/tokenization/__init__.py +0 -0
  135. src/tokenization/base.py +75 -0
  136. src/tokenization/bpe.py +190 -0
  137. src/tokenization/bytebpe.py +476 -0
  138. src/tokenization/registry.py +28 -0
  139. src/training/__init__.py +0 -0
  140. src/training/checkpoint_manager.py +101 -0
  141. src/training/experiment.py +71 -0
  142. src/training/losses.py +42 -0
  143. src/training/precision.py +141 -0
  144. src/training/profiler.py +38 -0
  145. src/training/scheduler.py +50 -0
  146. src/training/trainer.py +594 -0
@@ -0,0 +1,74 @@
1
+ from src.activations import activation_fns
2
+ from src.models.gpt.attention import CausalSelfAttention
3
+ from src.models.transformers.Dropout import Dropout
4
+ from src.models.transformers.LayerNorm import LayerNorm
5
+ from src.neural.Dense import Dense
6
+ from src.neural.Layer import Layer
7
+
8
+
9
+ class GPTBlock(Layer):
10
+
11
+ def __init__(self, config, rope=None):
12
+ super().__init__()
13
+
14
+ self.config = config
15
+
16
+ self.norm1 = LayerNorm(config.d_model, eps=config.norm_eps)
17
+ self.attn = CausalSelfAttention(config.d_model, config.n_heads, rope=rope)
18
+
19
+ self.norm2 = LayerNorm(config.d_model, eps=config.norm_eps)
20
+ self.fc1 = Dense(config.ff_dim)
21
+ self.fc2 = Dense(config.d_model)
22
+
23
+ self.dropout = Dropout(config.dropout)
24
+ self.activation = activation_fns[config.activation]
25
+
26
+ def build(self, input_shape):
27
+ self.norm1.build(input_shape)
28
+ self.attn.build(input_shape)
29
+
30
+ self.norm2.build(input_shape)
31
+ self.fc1.build(input_shape)
32
+
33
+ ff_shape = (*input_shape[:-1], self.fc1.units)
34
+ self.fc2.build(ff_shape)
35
+
36
+ self.dropout.build(input_shape)
37
+
38
+ self.built = True
39
+
40
+ def call(self, x, mask=None):
41
+ h = self.norm1.call(x)
42
+ h = self.attn.call(h, mask=mask)
43
+ x = x + self.dropout.call(h)
44
+
45
+ h = self.norm2.call(x)
46
+ h = self.fc2.call(self.activation(self.fc1.call(h)))
47
+ x = x + self.dropout.call(h)
48
+
49
+ return x
50
+
51
+ def parameters(self):
52
+ params = []
53
+ params.extend(self.norm1.parameters())
54
+ params.extend(self.attn.parameters())
55
+ params.extend(self.norm2.parameters())
56
+ params.extend(self.fc1.parameters())
57
+ params.extend(self.fc2.parameters())
58
+ return params
59
+
60
+ def state_dict(self):
61
+ return {
62
+ "norm1": self.norm1.state_dict(),
63
+ "attn": self.attn.state_dict(),
64
+ "norm2": self.norm2.state_dict(),
65
+ "fc1": self.fc1.state_dict(),
66
+ "fc2": self.fc2.state_dict(),
67
+ }
68
+
69
+ def load_state_dict(self, state):
70
+ self.norm1.load_state_dict(state["norm1"])
71
+ self.attn.load_state_dict(state["attn"])
72
+ self.norm2.load_state_dict(state["norm2"])
73
+ self.fc1.load_state_dict(state["fc1"])
74
+ self.fc2.load_state_dict(state["fc2"])
@@ -0,0 +1,103 @@
1
+ import json
2
+ from typing import Optional
3
+ from dataclasses import asdict, dataclass
4
+
5
+
6
+ SUPPORTED_ACTIVATIONS = ("gelu", "relu", "tanh", "sigmoid")
7
+ POSITION_ENCODINGS = ("learned", "rope")
8
+
9
+
10
+ @dataclass
11
+ class GPTConfig:
12
+ vocab_size: int
13
+ context_length: int = 1024
14
+ d_model: int = 768
15
+ n_layers: int = 12
16
+ n_heads: int = 12
17
+ ff_dim: int = 3072
18
+ activation: str = "gelu"
19
+ dropout: float = 0.0
20
+ norm_eps: float = 1e-5
21
+ tie_weights: bool = True
22
+ architecture: str = "gpt"
23
+ position_encoding: str = "learned"
24
+ rope_theta: float = 10000.0
25
+ rope_scaling: str = "none"
26
+ rope_scaling_factor: float = 1.0
27
+ trained_context_length: Optional[int] = None
28
+
29
+ def __post_init__(self):
30
+ if self.d_model % self.n_heads != 0:
31
+ raise ValueError("d_model must be divisible by n_heads")
32
+
33
+ if self.activation not in SUPPORTED_ACTIVATIONS:
34
+ raise ValueError(
35
+ f"unsupported activation '{self.activation}'; choose one of {SUPPORTED_ACTIVATIONS}"
36
+ )
37
+
38
+ if self.position_encoding not in POSITION_ENCODINGS:
39
+ raise ValueError(
40
+ f"unsupported position_encoding '{self.position_encoding}'; choose one of {POSITION_ENCODINGS}"
41
+ )
42
+
43
+ if self.position_encoding == "rope":
44
+ if (self.d_model // self.n_heads) % 2 != 0:
45
+ raise ValueError("rope needs an even head dimension (d_model / n_heads)")
46
+
47
+ if not self.rope_theta > 0:
48
+ raise ValueError("rope_theta must be positive")
49
+
50
+ if self.rope_scaling not in ("none", "linear", "ntk"):
51
+ raise ValueError(f"unknown rope_scaling '{self.rope_scaling}'; choose none, linear or ntk")
52
+
53
+ self.rope_scaling_factor = float(self.rope_scaling_factor)
54
+
55
+ if not self.rope_scaling_factor >= 1.0:
56
+ raise ValueError("rope_scaling_factor must be >= 1")
57
+
58
+ if (self.rope_scaling != "none" or self.trained_context_length is not None) and not self.uses_rope:
59
+ raise ValueError("context extension settings require position_encoding: rope")
60
+
61
+ if self.trained_context_length is not None and self.trained_context_length > self.context_length:
62
+ raise ValueError("trained_context_length cannot exceed context_length")
63
+
64
+ self.rope_theta = float(self.rope_theta)
65
+
66
+ @property
67
+ def head_dim(self):
68
+ return self.d_model // self.n_heads
69
+
70
+ @property
71
+ def uses_rope(self):
72
+ return self.position_encoding == "rope"
73
+
74
+ def to_dict(self):
75
+ return asdict(self)
76
+
77
+ @classmethod
78
+ def from_dict(cls, data):
79
+ known = set(cls.__dataclass_fields__.keys())
80
+ return cls(**{k: v for k, v in data.items() if k in known})
81
+
82
+ @property
83
+ def base_context_length(self):
84
+ return self.trained_context_length or self.context_length
85
+
86
+ def rotary_tables(self):
87
+ from src.models.gpt.rope import rotary_tables
88
+
89
+ return rotary_tables(self.head_dim, self.context_length, self.rope_theta,
90
+ self.rope_scaling, self.rope_scaling_factor)
91
+
92
+ @classmethod
93
+ def normalized(cls, data):
94
+ return cls.from_dict(data).to_dict()
95
+
96
+ def save(self, path):
97
+ with open(path, "w") as f:
98
+ json.dump(self.to_dict(), f, indent=2, sort_keys=True)
99
+
100
+ @classmethod
101
+ def load(cls, path):
102
+ with open(path) as f:
103
+ return cls.from_dict(json.load(f))
@@ -0,0 +1,44 @@
1
+ from dataclasses import replace
2
+
3
+ EXTENSION_METHODS = ("extrapolate", "linear", "ntk")
4
+
5
+
6
+ def extend_context(config, context_length, method):
7
+ if method not in EXTENSION_METHODS:
8
+ raise ValueError(f"unknown context extension method '{method}'; choose one of {EXTENSION_METHODS}")
9
+
10
+ if not config.uses_rope:
11
+ raise ValueError(
12
+ "context extension needs a rope model; learned positional embeddings have no entries past "
13
+ f"the trained length of {config.context_length}"
14
+ )
15
+
16
+ base = config.base_context_length
17
+ context_length = int(context_length)
18
+
19
+ if context_length <= base:
20
+ raise ValueError(f"extended context ({context_length}) must exceed the trained context ({base})")
21
+
22
+ factor = context_length / base
23
+ scaling = "none" if method == "extrapolate" else method
24
+
25
+ return replace(
26
+ config,
27
+ context_length=context_length,
28
+ trained_context_length=base,
29
+ rope_scaling=scaling,
30
+ rope_scaling_factor=1.0 if scaling == "none" else factor,
31
+ )
32
+
33
+
34
+ def describe_context(config):
35
+ if config.trained_context_length is None:
36
+ return {"context_length": config.context_length, "extended": False}
37
+
38
+ return {
39
+ "context_length": config.context_length,
40
+ "extended": True,
41
+ "trained_context_length": config.trained_context_length,
42
+ "method": "extrapolate" if config.rope_scaling == "none" else config.rope_scaling,
43
+ "factor": config.context_length / config.trained_context_length,
44
+ }
@@ -0,0 +1,165 @@
1
+ import numpy as np
2
+
3
+ from src.core.Tensor import Tensor
4
+ from src.models.embedding.Embedding import Embedding
5
+ from src.models.gpt.block import GPTBlock
6
+ from src.models.gpt.recompute import checkpoint
7
+ from src.models.transformers.LayerNorm import LayerNorm
8
+ from src.neural.Dense import Dense
9
+
10
+
11
+ class GPTModel:
12
+
13
+ def __init__(self, config):
14
+ self.config = config
15
+
16
+ self.token_emb = Embedding(config.vocab_size, config.d_model)
17
+
18
+ self.pos_emb = None
19
+ self.rope = None
20
+
21
+ if config.uses_rope:
22
+ self.rope = config.rotary_tables()
23
+ else:
24
+ self.pos_emb = Embedding(config.context_length, config.d_model)
25
+
26
+ self.blocks = [GPTBlock(config, rope=self.rope) for _ in range(config.n_layers)]
27
+
28
+ self.final_norm = LayerNorm(config.d_model, eps=config.norm_eps)
29
+
30
+ self.lm_head = None
31
+ if not config.tie_weights:
32
+ self.lm_head = Dense(config.vocab_size)
33
+
34
+ self.activation_checkpointing = False
35
+ self.training = True
36
+ self._built = False
37
+
38
+ def build(self):
39
+ if self._built:
40
+ return
41
+
42
+ self.token_emb.build((None, self.config.context_length))
43
+
44
+ if self.pos_emb is not None:
45
+ self.pos_emb.build((None, self.config.context_length))
46
+
47
+ block_shape = (None, self.config.context_length, self.config.d_model)
48
+
49
+ for block in self.blocks:
50
+ block.build(block_shape)
51
+
52
+ self.final_norm.build(block_shape)
53
+
54
+ if self.lm_head is not None:
55
+ self.lm_head.build(block_shape)
56
+
57
+ self._built = True
58
+
59
+ def forward(self, input_ids):
60
+ if not self._built:
61
+ self.build()
62
+
63
+ batch, seq_len = input_ids.shape
64
+
65
+ if seq_len > self.config.context_length:
66
+ raise ValueError(
67
+ f"sequence length {seq_len} exceeds context_length "
68
+ f"{self.config.context_length}"
69
+ )
70
+
71
+ x = self.token_emb.call(input_ids)
72
+
73
+ if self.pos_emb is not None:
74
+ positions = Tensor(
75
+ np.tile(np.arange(seq_len, dtype=np.float32), (batch, 1)),
76
+ requires_grad=False,
77
+ )
78
+ x = x + self.pos_emb.call(positions)
79
+
80
+ for block in self.blocks:
81
+ if self.activation_checkpointing:
82
+ x = checkpoint(block.call, x)
83
+ else:
84
+ x = block.call(x)
85
+
86
+ x = self.final_norm.call(x)
87
+
88
+ if self.lm_head is not None:
89
+ logits = self.lm_head.call(x)
90
+ else:
91
+ weight = self.token_emb.weight
92
+ flat = x.reshape(batch * seq_len, self.config.d_model)
93
+ logits = flat @ weight.transpose(1, 0)
94
+ logits = logits.reshape(batch, seq_len, self.config.vocab_size)
95
+
96
+ return logits
97
+
98
+ def __call__(self, input_ids):
99
+ return self.forward(input_ids)
100
+
101
+ def set_training(self, flag):
102
+ previous = self.training
103
+ self.training = bool(flag)
104
+
105
+ for block in self.blocks:
106
+ block.dropout.training = self.training
107
+
108
+ return previous
109
+
110
+ def parameters(self):
111
+ if not self._built:
112
+ self.build()
113
+
114
+ params = []
115
+ params.extend(self.token_emb.parameters())
116
+
117
+ if self.pos_emb is not None:
118
+ params.extend(self.pos_emb.parameters())
119
+
120
+ for block in self.blocks:
121
+ params.extend(block.parameters())
122
+
123
+ params.extend(self.final_norm.parameters())
124
+
125
+ if self.lm_head is not None:
126
+ params.extend(self.lm_head.parameters())
127
+
128
+ return params
129
+
130
+ def num_parameters(self):
131
+ return sum(p.data.size for p in self.parameters())
132
+
133
+ def state_dict(self):
134
+ state = {
135
+ "token_emb": self.token_emb.state_dict(),
136
+ "final_norm": self.final_norm.state_dict(),
137
+ "blocks": [b.state_dict() for b in self.blocks],
138
+ }
139
+
140
+ if self.pos_emb is not None:
141
+ state["pos_emb"] = self.pos_emb.state_dict()
142
+
143
+ if self.lm_head is not None:
144
+ state["lm_head"] = self.lm_head.state_dict()
145
+
146
+ return state
147
+
148
+ def load_state_dict(self, state):
149
+ if not self._built:
150
+ self.build()
151
+
152
+ if (self.pos_emb is not None) != ("pos_emb" in state):
153
+ raise ValueError("state does not match the model's position encoding")
154
+
155
+ self.token_emb.load_state_dict(state["token_emb"])
156
+
157
+ if self.pos_emb is not None:
158
+ self.pos_emb.load_state_dict(state["pos_emb"])
159
+ self.final_norm.load_state_dict(state["final_norm"])
160
+
161
+ for block, block_state in zip(self.blocks, state["blocks"]):
162
+ block.load_state_dict(block_state)
163
+
164
+ if self.lm_head is not None and "lm_head" in state:
165
+ self.lm_head.load_state_dict(state["lm_head"])
@@ -0,0 +1,35 @@
1
+ import numpy as np
2
+
3
+ from src.core.Tensor import Tensor, grad_enabled, no_grad
4
+
5
+
6
+ def checkpoint(fn, x):
7
+ if not grad_enabled():
8
+ return fn(x)
9
+
10
+ rng_state = np.random.get_state()
11
+
12
+ with no_grad():
13
+ y_data = fn(Tensor(x.data, requires_grad=False)).data
14
+
15
+ out = Tensor(y_data, requires_grad=True, parents=(x,), op="Checkpoint")
16
+
17
+ def _backward():
18
+ resume_state = np.random.get_state()
19
+ np.random.set_state(rng_state)
20
+
21
+ try:
22
+ x_local = Tensor(x.data, requires_grad=True)
23
+ y = fn(x_local)
24
+ finally:
25
+ np.random.set_state(resume_state)
26
+
27
+ y.backward(out.grad, release=True)
28
+
29
+ if x.requires_grad:
30
+ x.grad += x_local.grad
31
+
32
+ out._backward = _backward
33
+
34
+ return out
35
+
src/models/gpt/rope.py ADDED
@@ -0,0 +1,84 @@
1
+ import threading
2
+
3
+ import numpy as np
4
+
5
+
6
+ ROPE_SCALING = ("none", "linear", "ntk")
7
+
8
+
9
+ def scaled_theta(theta, head_dim, scaling, factor):
10
+ if scaling == "ntk":
11
+ return float(theta) * float(factor) ** (head_dim / (head_dim - 2))
12
+
13
+ return float(theta)
14
+
15
+
16
+ class RotaryTables:
17
+
18
+ def __init__(self, head_dim, max_positions, theta=10000.0, scaling="none", factor=1.0):
19
+ if head_dim % 2 != 0:
20
+ raise ValueError("rotary position encoding needs an even head dimension")
21
+
22
+ if scaling not in ROPE_SCALING:
23
+ raise ValueError(f"unknown rope scaling '{scaling}'; choose one of {ROPE_SCALING}")
24
+
25
+ if not factor >= 1.0:
26
+ raise ValueError("rope scaling factor must be >= 1")
27
+
28
+ self.head_dim = head_dim
29
+ self.half = head_dim // 2
30
+ self.scaling = scaling
31
+ self.factor = float(factor)
32
+ self.theta = scaled_theta(theta, head_dim, scaling, factor)
33
+ self.max_positions = int(max_positions)
34
+
35
+ inv_freq = self.theta ** (-np.arange(0, self.half, dtype=np.float64) / self.half)
36
+ positions = np.arange(self.max_positions, dtype=np.float64)
37
+
38
+ if scaling == "linear":
39
+ positions = positions / self.factor
40
+
41
+ angles = positions[:, None] * inv_freq[None, :]
42
+
43
+ self.cos = np.cos(angles).astype(np.float32)
44
+ self.sin = np.sin(angles).astype(np.float32)
45
+
46
+ def tables(self, positions):
47
+ positions = np.asarray(positions, dtype=np.int64)
48
+
49
+ if positions.size and (positions.min() < 0 or positions.max() >= self.max_positions):
50
+ raise ValueError(f"position outside the rotary table (0..{self.max_positions - 1})")
51
+
52
+ return self.cos[positions], self.sin[positions]
53
+
54
+ def rotate(self, x, cos, sin, inverse=False):
55
+ h = self.half
56
+ x1 = x[..., :h]
57
+ x2 = x[..., h:]
58
+ out = np.empty_like(x)
59
+
60
+ if inverse:
61
+ out[..., :h] = x1 * cos + x2 * sin
62
+ out[..., h:] = x2 * cos - x1 * sin
63
+ else:
64
+ out[..., :h] = x1 * cos - x2 * sin
65
+ out[..., h:] = x2 * cos + x1 * sin
66
+
67
+ return out
68
+
69
+
70
+ _cache = {}
71
+ _cache_lock = threading.Lock()
72
+
73
+
74
+ def rotary_tables(head_dim, max_positions, theta=10000.0, scaling="none", factor=1.0):
75
+ key = (int(head_dim), int(max_positions), float(theta), scaling, float(factor))
76
+
77
+ with _cache_lock:
78
+ tables = _cache.get(key)
79
+
80
+ if tables is None:
81
+ tables = RotaryTables(head_dim, max_positions, theta, scaling, factor)
82
+ _cache[key] = tables
83
+
84
+ return tables
@@ -0,0 +1,51 @@
1
+ import numpy as np
2
+
3
+ from src.core.Tensor import Tensor
4
+
5
+
6
+ # y = XW + B
7
+ class Linear:
8
+ def __init__(self, weight_shape, bias_shape):
9
+
10
+ self.W = Tensor.random(weight_shape)
11
+
12
+ self.b = Tensor.random(bias_shape)
13
+
14
+ self.dW = Tensor.zeros(weight_shape)
15
+ self.db = Tensor.zeros(bias_shape)
16
+
17
+ self.X = None
18
+
19
+ def normalize(self, X):
20
+ norm = np.linalg.norm(X)
21
+ return X if norm == 0 else X / norm
22
+
23
+ def forward(self, X):
24
+ self.X = X
25
+ return np.dot(X, self.W.data) + self.b.data
26
+
27
+ def grads(self):
28
+ return [self.dW, self.db]
29
+
30
+ def parameters(self):
31
+ return [self.W, self.b]
32
+
33
+ def backward(self, grad_output):
34
+ # L = pred - target
35
+ # u = pred - target
36
+ # L = u
37
+ # dL/du = 1
38
+ # dL/dpred = dL/du * du/dpred
39
+ # du/dpred = 1 - 0 = 1
40
+ # dL/dpred = u = pred - target
41
+ # how do W affect the L?
42
+ # dL/dW = dL/dpred * dpred/dW
43
+ # dpred/dW = X
44
+ # dL/dW = (pred - target) * X
45
+ self.dW.data += grad_output * self.X.data
46
+ self.db.data += grad_output
47
+ return grad_output * self.W.data
48
+
49
+ def update(self, learning_rate):
50
+ self.W.data -= learning_rate * self.dW.data
51
+ self.b.data -= learning_rate * self.db.data
@@ -0,0 +1,36 @@
1
+ import numpy as np
2
+
3
+ from src.core.Tensor import Tensor
4
+ from src.math.sigmoid import sigmoid
5
+
6
+
7
+ class Logistic:
8
+ def __init__(self, weight_shape, bias_shape):
9
+ self.X = None
10
+ self.W = Tensor(weight_shape)
11
+ self.W.random()
12
+
13
+ self.b = Tensor(bias_shape)
14
+ self.b.random()
15
+
16
+ self.dW = Tensor(weight_shape)
17
+ self.db = Tensor(bias_shape)
18
+
19
+ def grads(self):
20
+ return [self.dW, self.db]
21
+
22
+ def parameters(self):
23
+ return [self.W, self.b]
24
+
25
+ def forward(self, X):
26
+ self.X = X
27
+ return sigmoid(np.dot(X, self.W.data) + self.b.data)
28
+
29
+ def backward(self, grad_output):
30
+ self.dW.data += grad_output * self.X.data
31
+ self.db.data += grad_output
32
+ return grad_output * self.W.data
33
+
34
+ def update(self, learning_rate):
35
+ self.W.data -= learning_rate * self.dW.data
36
+ self.b.data -= learning_rate * self.db.data
File without changes