Skip to content

Commit f054597

Browse files
committed
Merge branch 'master' of https://github.com/boris-kz/CogAlg
# Conflicts: # frame_2D_alg/agg_recursion.py # frame_2D_alg/agg_recursion_nested.py # frame_2D_alg/comp_utils.py # frame_2D_alg/vect_edge.py
2 parents 3cb4aef + 15a694f commit f054597

14 files changed

+56
-1279
lines changed

README.md

+7-7
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
11
CogAlg
22
======
33

4-
I am designing this algorithm for comprehensive hierarchical clustering, from pixels to eternity. It stems from the definition of intelligence as the ability to predict from prior / adjacent inputs. That includes much-ballyhooed reasoning and planning: basically tracing connections in segmented graphs. Any prediction is interactive projection of known patterns, hence primary process must be pattern discovery (AKA unsupervised learning: an obfuscating negation-first term). This perspective is not novel, pattern recognition is a main focus of ML, and a core of any IQ test. The problem I have with statistical ML is the process: it discards crucial positional info, so resulting patterns are indirectly centroid-based.
4+
I design this algorithm for comprehensive hierarchical clustering, from pixels to eternity. It stems from the definition of intelligence as the ability to predict from prior / adjacent inputs. Which is basically tracing connections in segmented graphs, including much-ballyhooed reasoning and planning. Any prediction is interactive projection of known patterns, hence primary process must be pattern discovery (AKA unsupervised learning: an obfuscating negation-first term). This perspective is not novel, pattern recognition is a main focus of ML, and a core of any IQ test. The problem I have with statistical ML is the process: it ignores crucial positional info, thus resulting patterns are effectively centroid-based.
55

6-
Pattern recognition is a default mode in Neural Nets, but they work indirectly, in a very coarse statistical fashion. Basic NN, such as [multi-layer perceptron](https://towardsdatascience.com/what-the-hell-is-perceptron-626217814f53) or [KAN](https://towardsdatascience.com/kolmogorov-arnold-networks-kan-e317b1b4d075), performs lossy stochastic chain-rule curve fitting. Each node outputs a normalized sum of weighted inputs, then adjusts the weights in proportion to modulated similarity between input and output. In Deep Learning, this adjustment is mediated by backprop of decomposed error (inverse similarity) from the output layer. In Hebbian Learning, it's a more direct adjustment by local output/input coincidence: a binary version of their similarity. It's the same logic as in centroid-based clustering, but non-linear and fuzzy (fully connected in MLP), with a vector of centroids and multi-layer summation / credit allocation in backprop.
6+
Pattern recognition is a default mode in Neural Nets, but they work indirectly, in a very coarse statistical fashion. Basic NN, such as [multi-layer perceptron](https://towardsdatascience.com/what-the-hell-is-perceptron-626217814f53) or [KAN](https://towardsdatascience.com/kolmogorov-arnold-networks-kan-e317b1b4d075), performs lossy stochastic chain-rule curve fitting. Each node outputs a normalized sum of weighted inputs, which adjusts the weights in proportion to modulated similarity between input and output. In Deep Learning, this adjustment is by backprop of decomposed error (inverse similarity) from the output layer. In Hebbian Learning, it's a more direct adjustment by local output/input coincidence: a binary version of direct similarity. The logic is basically the same as in centroid-based clustering, but non-linear and fuzzy (fully connected in MLP), with a vector of centroids and multi-layer summation / distribution in backprop.
77

88
Modern ANNs combine such vertical training with lateral cross-correlation, within an input vector. CNN filters are designed to converge on edge-detection in initial layers. Edge detection means computing lateral gradient, by weighted pixel cross-comparison within kernels. Graph NNs embed lateral edges, representing similarity or/and difference between nodes, also produced by their cross-comparison. Popular [transformers](https://www.quantamagazine.org/researchers-glimpse-how-ai-gets-so-good-at-language-processing-20220414/) can be seen as a [variation of Graph NN](https://towardsdatascience.com/transformers-are-graph-neural-networks-bca9f75412aa). Their first step is self-attention: computing dot product between KV vectors within context window of an input. This is a form of cross-comparison because dot product serves as a measure of similarity, just an unprincipled one.
99

1010
So basic operation in both trained CNN and self-attention is what I call cross-comparison, but the former selects for variance and the latter for similarity. I think the difference is due to relative rarity of each in respective target data: mostly low gradients in raw images and sparse similarities in compressed text. This rarity or surprise determines information content of the input. But almost all text ultimately describes generalized images and objects therein, so there should be a gradual transition between the two. In my scheme higher-level cross-comparison computes both variance and similarity, for differential clustering.
1111

12-
GNN, transformers, and Hinton's [Capsule Networks](https://medium.com/ai%C2%B3-theory-practice-business/understanding-hintons-capsule-networks-part-i-intuition-b4b559d1159b) all have positional embeddings, as I use explicit coordinates. But they are still trained through destructive backprop: randomized summation first, meaningful output-to-template comparison last. This primary summation degrades resolution of the whole learning process, exponentially with the number of layers. Hence, a ridiculous number of backprop cycles is needed to fit hidden layers into generalized representations (patterns) of the input. Most practitioners agree that this process is not very smart, the noise-worshiping alone is the definition of stupidity. I think it's just a low-hanging fruit for terminally lazy evolution, and slightly more disciplined human coding. It's also easy to parallelize, which is crucial for glacially slow cell-based biology.
12+
GNN, transformers, and Hinton's [Capsule Networks](https://medium.com/ai%C2%B3-theory-practice-business/understanding-hintons-capsule-networks-part-i-intuition-b4b559d1159b) all have positional embeddings, as I use explicit coordinates. But they are still trained through destructive backprop: randomized summation first, meaningful output-to-template comparison last. This primary summation degrades resolution of the whole learning process, exponentially with the number of layers. Hence, a ridiculous number of backprop cycles is needed to fit hidden layers into generalized representations of the input. Most practitioners agree that this process is not very smart, the noise-worship alone is the definition of stupidity. It's just a low-hanging fruit for terminally lazy evolution, and slightly more disciplined human coding. And easily parallelizable, which is crucial for glacially slow cell-based biology.
1313

1414
Graceful conditional degradation requires reversed sequence: first cross-comp of original inputs, then summing them into match-defined clusters. That's a lateral [connectivity-based clustering](https://en.wikipedia.org/wiki/Cluster_analysis#Connectivity-based_clustering_(hierarchical_clustering)), vs. vertical statistical fitting in NN. This cross-comp and clustering is recursively hierarchical, forming patterns of patterns and so on. Initial connectivity is in space-time, but feedback will reorder input along all sufficiently predictive derived dimensions (eigenvectors). This is similar to [spectral clustering](https://en.wikipedia.org/wiki/Spectral_clustering), but the last step is still connectivity clustering, in new frame of reference. Feedback will only adjust hyperparameters to filter future inputs: no top-down training, just bottom-up learning.
1515

16-
Connectivity likely represents local interactions, which may form a heterogeneous or differentiated system. Such differentiation may be functional, with internal variation contributing to whole-system stability. The most basic example is contours in images, which may represent object resilience to external impact and are generally more informative than fill-in areas. Cross-similarity is not likely to continue immediately beyond such contours. So next cross-comp is discontinuous and should be selective for well-defined and stable core + contour clusters.
16+
Connectivity likely represents local interactions, which may form both similarity clusters and their high-variance boundaries. Such boundaries reflect stability (resilience to external impact) of the core similarity cluster. The most basic example is image contours, which are initially more informative than flat areas. Cross-similarity is not likely to continue immediately beyond such contours, so they also represent "separability" of the core cluster. Thus, the next cross-comp should be discontinuous and on a higher-composition level: between previously formed complemented cluster + contour representations. This is much more expensive: the clusters are complex and compared over greater distance (number of combinations).
1717

18-
At this point centroid clustering of previously formed connectivity clusters makes sense: it's a global selection by mutual similarity. Only centroids (exemplars) need to be cross-compared on the next connectivity clustering level, as they effectively represent their nodes. So hierarchical clustering (learning) should alternate between these two phases:
19-
- connectivity clustering is a generative learning phase, forming new derivatives and structured composition levels,
20-
- centroid clustering is a compressive phase, reducing multiple similar comparands to a single exemplar.
18+
So higher cross-comp should be selective for high core_similarity + contour_variance (borrowed from average local cross-similarity). And it should be global: complemented clusters are inherently discontinuous. That means centroid clustering, and next connectivity clustering level will cross-comp resulting centroids (exemplars). These two clustering phases should alternate hierarchically:
19+
- connectivity clustering as a generative phase, forming new derivatives and structured composition levels,
20+
- centroid clustering as a compressive phase, reducing multiple similar comparands to a single exemplar.
2121

2222
While connectivity clustering is among the oldest methods in ML, I believe my scheme is uniquely scalable in complexity of discoverable patterns:
2323
- Links are valued by both similarity and variance between the nodes.

frame_2D_alg/agg_recursion.py

+4-10
Original file line numberDiff line numberDiff line change
@@ -21,29 +21,23 @@ def cross_comp(root): # breadth-first node_,link_ cross-comp, connect.clusterin
2121
N_,L_,Et = comp_node_(root.subG_) # cross-comp exemplars, extrapolate to their node_s
2222
# mfork
2323
if val_(Et, fo=1) > 0:
24-
H = root.derH # for both forks
25-
mlay = CH().add_tree([L.derH for L in L_]); mlay.root = H; H.Et += mlay.Et; H.lft = [mlay]; H.tft = mlay.tft
24+
mlay = CH().add_tree([L.derH for L in L_]); H=root.derH; mlay.root=H; H.Et += mlay.Et; H.lft = [mlay]
2625
pL_ = {l for n in N_ for l,_ in get_rim(n, fd=0)}
2726
if len(pL_) > ave_L:
2827
cluster_N_([root], pL_, fd=0) # optional divisive clustering, calls centroid and higher connect.clustering
2928
# dfork
3029
if val_(Et, mEt=Et,fo=1) > 0: # same root for L_, root.link_ was compared in root-forming for alt clustering
31-
convert_L_(L_,root)
30+
for L in L_:
31+
L.extH, L.root, L.Et, L.mL_t, L.rimt, L.aRad, L.visited_ = CH(),[root],copy(L.derH.Et),[[],[]], [[],[]], 0,[L]
3232
lN_,lL_,dEt = comp_link_(L_,Et)
3333
if val_(dEt, mEt=Et, fo=1) > 0:
34-
dlay = CH().add_tree([L.derH for L in lL_]); dlay.root = H; H.Et += dlay.Et; H.lft += [dlay]
34+
dlay = CH().add_tree([L.derH for L in lL_]); dlay.root=H; H.Et += dlay.Et; H.lft += [dlay]
3535
plL_ = {l for n in lN_ for l,_ in get_rim(n, fd=1)}
3636
if len(plL_) > ave_L:
3737
cluster_N_([root], plL_, fd=1)
3838

3939
feedback(root) # add root derH to higher roots derH
4040

41-
def convert_L_(L_, root):
42-
for L in L_:
43-
L.extH, L.mL_t, L.rimt, L.aRad, L.visited_ = CH(), [[],[]], [[],[]], 0, [L]
44-
L.root = [root]; L.Et = copy(L.derH.Et) # convert to root_ (L.root should be empty here? Because all new L doesn't have root assigned before they become node)
45-
46-
4741
def cluster_N_(root_, L_, fd, nest=0): # top-down segment L_ by >ave ratio of L.dists
4842

4943
L_ = sorted(L_, key=lambda x: x.dist, reverse=True) # current and shorter links

frame_2D_alg/vectorize_edge_blob/agg_compress.py frame_2D_alg/alternative versions/agg_compress.py

+5-8
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
1-
import numpy as np
21
from copy import deepcopy, copy
3-
from itertools import zip_longest, combinations
4-
from collections import deque, defaultdict
5-
from .classes import Cgraph, CderG, Cmd
6-
from .filters import ave_dangle, ave, ave_distance, G_aves, ave_Gm, ave_Gd, ave_dI
7-
from .slice_edge import slice_edge, comp_angle
8-
from .comp_slice import comp_P_, comp_ptuple, comp_derH, sum_derH, sum_dertuple, get_match
9-
from .agg_recursion import unpack_rim, node_connect, segment_node_, comp_G, comp_aggHv, comp_derHv, sum_derHv, sum_ext, sum_subHv, sum_aggHv
2+
from .classes import Cgraph, CderG
3+
from .filters import ave, G_aves
4+
from frame_2D_alg.slice_edge import slice_edge
5+
from frame_2D_alg.comp_slice import comp_P_
6+
from frame_2D_alg.agg_recursion import node_connect, segment_node_
107

118
'''
129
Implement sparse param tree in aggH: new graphs represent only high m|d params + their root params.

frame_2D_alg/vectorize_edge_blob/agg_kernels.py frame_2D_alg/alternative versions/agg_kernels.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import numpy as np
22
from copy import deepcopy, copy
3-
from itertools import combinations, zip_longest
4-
from .slice_edge import comp_angle, CsliceEdge, Clink, comp_ext, CP
5-
from .comp_slice import ider_recursion, comp_latuple, get_match
6-
from .filters import aves, ave_mL, ave_dangle, ave, G_aves, ave_Gm, ave_Gd, ave_dist, ave_mA, max_dist
3+
from itertools import combinations
4+
from frame_2D_alg.slice_edge import comp_angle, CsliceEdge, Clink, comp_ext
5+
from frame_2D_alg.comp_slice import ider_recursion, comp_latuple, get_match
6+
from .filters import ave, G_aves, ave_Gm, ave_dist, ave_mA
77
from utils import box2center, extend_box
88
import sys
99
sys.path.append("..")

frame_2D_alg/frame_graphs.py frame_2D_alg/alternative versions/frame_graphs.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
from class_cluster import CBase, comp_param
66
from frame_blobs import CBlob
7-
from frame_2D_alg.vectorize_edge_blob.comp_slice import ave, ave_daangle, ave_dx, ave_Ma, ave_inv # facing error when comp-slice_ import from comp_blob, hence shift it here.
7+
from frame_2D_alg.comp_slice import ave, ave_daangle, ave_dx, ave_Ma, ave_inv # facing error when comp-slice_ import from comp_blob, hence shift it here.
88
from intra_blob import intra_blob_root
99
import numpy as np
1010
import cv2

frame_2D_alg/comp_slice.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import numpy as np
22
from frame_blobs import CBase, frame_blobs_root, intra_blob_root, imread, unpack_blob_
3-
from slice_edge import CP, slice_edge, comp_angle, ave_G, ave_I
3+
from frame_2D_alg.slice_edge import CP, slice_edge, comp_angle, ave_G
4+
45
'''
56
comp_slice traces edge axis by cross-comparing vertically adjacent Ps: horizontal slices across an edge blob.
67
These are low-M high-Ma blobs, vectorized into outlines of adjacent flat (high internal match) blobs.
@@ -235,7 +236,7 @@ def min_dist(a, b, pad=0.5):
235236
# draw PPds as graphs of dPs and ddPs
236237
# dPs are shown in black, ddPs are shown in red
237238
import matplotlib.pyplot as plt
238-
from slice_edge import unpack_edge_
239+
from frame_2D_alg.slice_edge import unpack_edge_
239240
num_to_show = 5
240241
edge_ = sorted(
241242
filter(lambda edge: hasattr(edge, "node_") and edge.node_, unpack_edge_(frame)),

frame_2D_alg/deprecated/23.10.link_H.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import numpy as np
2-
from copy import copy, deepcopy
2+
from copy import deepcopy
33
from itertools import zip_longest
44
from collections import deque, defaultdict
5-
from frame_2D_alg.vectorize_edge_blob.slice_edge import comp_angle
5+
from frame_2D_alg.slice_edge import comp_angle
66
from frame_2D_alg.vectorize_edge_blob.classes import CderP, CPP
77
from frame_2D_alg.vectorize_edge_blob.filters import ave, aves, P_aves, PP_aves
88

frame_2D_alg/deprecated/link_Ht.py

+7-12
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
1-
import numpy as np
2-
from copy import deepcopy, copy
3-
from itertools import zip_longest
41
from frame_2D_alg.vectorize_edge_blob.classes import Cgraph, CderG
5-
from frame_2D_alg.vectorize_edge_blob.filters import aves, ave, ave_nsubt, ave_sub, ave_agg, G_aves, med_decay, ave_distance, ave_Gm, ave_Gd
6-
from frame_2D_alg.vectorize_edge_blob.comp_slice import comp_angle, comp_ptuple, sum_ptuple, sum_derH, comp_derH, comp_aangle
2+
from frame_2D_alg.vectorize_edge_blob.filters import ave_sub, ave_agg, G_aves, ave_distance, ave_Gm, ave_Gd
3+
from frame_2D_alg.comp_slice import comp_angle, comp_ptuple, sum_ptuple, comp_derH, comp_aangle
74
# from .sub_recursion import feedback # temporary
85

96
'''
@@ -440,10 +437,8 @@ def sum_aggH(T, t, base_rdn):
440437
else:
441438
AggH[:] = deepcopy(aggH)
442439

443-
import numpy as np
444-
from itertools import zip_longest
445-
from copy import copy, deepcopy
446-
from frame_2D_alg.vectorize_edge_blob.classes import CderP, CPP
440+
441+
from frame_2D_alg.vectorize_edge_blob.classes import CderP
447442
from frame_2D_alg.vectorize_edge_blob.filters import ave, aves, vaves, ave_dangle, ave_daangle,med_decay, aveB, P_aves
448443

449444
'''
@@ -732,9 +727,9 @@ def comp_aangle(_aangle, aangle):
732727
import numpy as np
733728
from copy import copy, deepcopy
734729
from frame_2D_alg.vectorize_edge_blob.filters import PP_aves, ave_nsubt
735-
from frame_2D_alg.vectorize_edge_blob.classes import CP, CPP
736-
from frame_2D_alg.vectorize_edge_blob.comp_slice import comp_P, form_PP_t, sum_derH
737-
from dataclasses import replace
730+
from frame_2D_alg.vectorize_edge_blob.classes import CPP
731+
from frame_2D_alg.comp_slice import comp_P, form_PP_t, sum_derH
732+
738733
'''
739734
Nesting in dH, implicit or explicit, is added by each layer of comp, which forms dderH | dH.
740735
That dH has the same nesting as compared G.H, but then G.H += [dH].

0 commit comments

Comments
 (0)