DEV Community

Yoshihiro Hasegawa
Yoshihiro Hasegawa

Posted on

p-adic Deep Learning Notebook

Hello dev.to community! 👋

Welcome to an interactive exploration of p-adic deep learning.

Preliminaries on $p$-adic Numbers

We'll work with rational numbers represented using Python's Fraction and define the p-adic norm and valuation.

from fractions import Fraction def padic_valuation(x: Fraction, p: int = 5) -> int: """ Compute the p-adic valuation v_p(x) for x in Q (Fraction). """ if x == 0: return float('inf') num, den = x.numerator, x.denominator v_num = 0 while num % p == 0: num //= p v_num += 1 v_den = 0 while den % p == 0: den //= p v_den += 1 return v_num - v_den def padic_norm(x: Fraction, p: int = 5) -> float: """ Return |x|_p = p^{-v_p(x)}. """ v = padic_valuation(x, p) if v == float('inf'): return 0.0 return p ** (-v) # Example a = Fraction(25, 2) b = Fraction(3, 125) print('v_5(a)=', padic_valuation(a,5), ', |a|_5=', padic_norm(a,5)) print('v_5(b)=', padic_valuation(b,5), ', |b|_5=', padic_norm(b,5)) 
Enter fullscreen mode Exit fullscreen mode

p-adic Neuron Implementation

Define a simple p-adic neuron with weights, bias, and a linear activation.

from fractions import Fraction class PadicNeuron: def __init__(self, weights, bias, p=5): # weights: list of Fraction, bias: Fraction self.weights = weights self.bias = bias self.p = p def forward(self, x): # x: list of Fraction z = sum(w * xi for w, xi in zip(self.weights, x)) + self.bias return z, padic_norm(z, self.p) # Example usage w = [Fraction(2), Fraction(3)] b = Fraction(1) neuron = PadicNeuron(w, b, p=5) x = [Fraction(1), Fraction(5, 2)] z, norm_z = neuron.forward(x) print('z =', z, ', |z|_5 =', norm_z) 
Enter fullscreen mode Exit fullscreen mode

Forward Pass Example

Let's see how the neuron behaves on a sample input vector.

# Multiple inputs demonstration inputs = [ [Fraction(1), Fraction(5,2)], [Fraction(25,1), Fraction(1,5)] ] for x in inputs: z, nz = neuron.forward(x) print(f"Input {x} -> z = {z}, |z|_5 = {nz}") 
Enter fullscreen mode Exit fullscreen mode

Next Steps

  • Extend to multi-layer p-adic networks
  • Implement p-adic backpropagation
  • Explore convergence under p-adic norms

Happy experimenting! 🎉

Theoretical Connections

  • Berkovich Spaces: We operate on Q (rationals), representing Type 1 points. The p-adic norm defines a non-Archimedean geometry where these points live. Other point types (like Type 2, Gauss points related to disks) exist and are crucial for a deeper analysis (analytification) of algebraic varieties over p-adic fields.

  • Stability (Theta-Slopes): Our activation |z|_p <= 1 relates to stability concepts. In more advanced theories (like theta-slopes for vector bundles or quiver representations), stability is defined using weighted averages (slopes) and determines how objects decompose or behave under certain operations. The p-adic norm provides a basic version.

  • Balancing Conditions (Metric Graphs): Balancing conditions on graphs, often related to Laplacians (like Kirchhoff's law), connect to ideas of equilibrium or harmonicity. In neural networks, similar concepts might appear in weight regularization, gradient flow, or information propagation dynamics, potentially analyzed using p-adic tools.

  • Hopf Algebra (Connes-Kreimer): This provides an algebraic framework for renormalization and handling hierarchical structures (like trees). Deep neural networks have a compositional structure (layers) that might, in principle, be studied using Hopf algebraic tools, though this is a highly abstract perspective.

Future Directions

  • Implement backpropagation for p-adic networks.
  • Explore different activation functions.
  • Use finite-precision p-adic arithmetic (e.g., Hensel codes).
  • Apply these networks to specific tasks (e.g., number theory, hierarchical data).
  • Investigate convergence properties under p-adic norms.
  • Extend the framework to multi-layer p-adic networks.

References

  • DOI

bitbucket.org

Segre Embedding Implementation

The Segre embedding maps $athbb{P}^1 imes athbb{P}^1$ into $athbb{P}^3$. This implementation computes the embedding for given projective coordinates.

def segre_embedding(p1, p2): """ Compute the Segre embedding of two projective points [a:b] and [c:d] into [ac:ad:bc:bd]. """ if len(p1) != 2 or len(p2) != 2: raise ValueError('Each input must be a projective point with two coordinates.') a, b = p1 c, d = p2 return [a * c, a * d, b * c, b * d] # Example usage p1 = [1, 0] p2 = [0, 1] print('Segre embedding:', segre_embedding(p1, p2)) 
Enter fullscreen mode Exit fullscreen mode

Balancing Conditions on Metric Graphs

This implementation verifies the balancing condition on a metrized graph.

class MetrizedGraph: def __init__(self, vertices, edges, lengths): """ Initialize a metrized graph with vertices, edges, and edge lengths. vertices: List of vertex identifiers edges: List of tuples (start, end) representing edges lengths: Dictionary mapping edges to positive lengths """ self.vertices = vertices self.edges = edges self.lengths = lengths def verify_balancing_condition(self, weights): """ Verify the balancing condition: For each edge (u, v), w(u)/l + w(v)/l = 0. """ for edge in self.edges: u, v = edge l = self.lengths[edge] if weights[u] / l + weights[v] / l != 0: return False return True # Example usage vertices = ['A', 'B'] edges = [('A', 'B')] lengths = {('A', 'B'): 1.0} weights = {'A': 1, 'B': -1} graph = MetrizedGraph(vertices, edges, lengths) print('Balancing condition satisfied:', graph.verify_balancing_condition(weights)) 
Enter fullscreen mode Exit fullscreen mode

Top comments (0)