├── .gitignore ├── documentation └── output.jpg ├── elefant_exceptions.py ├── generic.py ├── images ├── img1.png ├── img10.png ├── img100.png ├── img101.png ├── img102.png ├── img103.png ├── img104.png ├── img105.png ├── img106.png ├── img107.png ├── img108.png ├── img109.png ├── img11.png ├── img110.png ├── img111.png ├── img112.png ├── img113.png ├── img114.png ├── img115.png ├── img116.png ├── img117.png ├── img118.png ├── img119.png ├── img12.png ├── img120.png ├── img121.png ├── img122.png ├── img123.png ├── img124.png ├── img125.png ├── img126.png ├── img127.png ├── img128.png ├── img129.png ├── img13.png ├── img130.png ├── img131.png ├── img132.png ├── img133.png ├── img134.png ├── img135.png ├── img136.png ├── img137.png ├── img138.png ├── img139.png ├── img14.png ├── img140.png ├── img141.png ├── img142.png ├── img143.png ├── img144.png ├── img145.png ├── img146.png ├── img147.png ├── img148.png ├── img149.png ├── img15.png ├── img150.png ├── img151.png ├── img152.png ├── img153.png ├── img154.png ├── img155.png ├── img156.png ├── img157.png ├── img158.png ├── img159.png ├── img16.png ├── img160.png ├── img161.png ├── img162.png ├── img163.png ├── img164.png ├── img165.png ├── img166.png ├── img167.png ├── img168.png ├── img169.png ├── img17.png ├── img170.png ├── img171.png ├── img172.png ├── img173.png ├── img174.png ├── img175.png ├── img176.png ├── img177.png ├── img178.png ├── img179.png ├── img18.png ├── img180.png ├── img181.png ├── img182.png ├── img183.png ├── img184.png ├── img185.png ├── img186.png ├── img187.png ├── img188.png ├── img189.png ├── img19.png ├── img190.png ├── img191.png ├── img192.png ├── img193.png ├── img194.png ├── img195.png ├── img196.png ├── img197.png ├── img198.png ├── img199.png ├── img2.png ├── img20.png ├── img200.png ├── img201.png ├── img202.png ├── img203.png ├── img204.png ├── img205.png ├── img206.png ├── img207.png ├── img208.png ├── img209.png ├── img21.png ├── img210.png ├── img211.png ├── img212.png ├── img213.png ├── img214.png ├── img215.png ├── img216.png ├── img217.png ├── img218.png ├── img219.png ├── img22.png ├── img220.png ├── img221.png ├── img222.png ├── img223.png ├── img224.png ├── img225.png ├── img226.png ├── img227.png ├── img228.png ├── img229.png ├── img23.png ├── img230.png ├── img231.png ├── img232.png ├── img233.png ├── img234.png ├── img235.png ├── img236.png ├── img237.png ├── img238.png ├── img239.png ├── img24.png ├── img240.png ├── img241.png ├── img242.png ├── img243.png ├── img244.png ├── img245.png ├── img246.png ├── img247.png ├── img248.png ├── img249.png ├── img25.png ├── img250.png ├── img251.png ├── img252.png ├── img253.png ├── img254.png ├── img255.png ├── img256.png ├── img257.png ├── img258.png ├── img259.png ├── img26.png ├── img260.png ├── img261.png ├── img262.png ├── img263.png ├── img264.png ├── img265.png ├── img266.png ├── img267.png ├── img268.png ├── img269.png ├── img27.png ├── img270.png ├── img271.png ├── img272.png ├── img273.png ├── img274.png ├── img275.png ├── img276.png ├── img277.png ├── img278.png ├── img279.png ├── img28.png ├── img280.png ├── img281.png ├── img282.png ├── img283.png ├── img284.png ├── img285.png ├── img286.png ├── img287.png ├── img288.png ├── img289.png ├── img29.png ├── img290.png ├── img291.png ├── img292.png ├── img293.png ├── img294.png ├── img295.png ├── img296.png ├── img297.png ├── img298.png ├── img299.png ├── img3.png ├── img30.png ├── img300.png ├── img301.png ├── img302.png ├── img303.png ├── img304.png ├── img305.png ├── img306.png ├── img307.png ├── img308.png ├── img309.png ├── img31.png ├── img310.png ├── img311.png ├── img312.png ├── img313.png ├── img314.png ├── img315.png ├── img316.png ├── img317.png ├── img318.png ├── img319.png ├── img32.png ├── img320.png ├── img33.png ├── img34.png ├── img35.png ├── img36.png ├── img37.png ├── img38.png ├── img39.png ├── img4.png ├── img40.png ├── img41.png ├── img42.png ├── img43.png ├── img44.png ├── img45.png ├── img46.png ├── img47.png ├── img48.png ├── img49.png ├── img5.png ├── img50.png ├── img51.png ├── img52.png ├── img53.png ├── img54.png ├── img55.png ├── img56.png ├── img57.png ├── img58.png ├── img59.png ├── img6.png ├── img60.png ├── img61.png ├── img62.png ├── img63.png ├── img64.png ├── img65.png ├── img66.png ├── img67.png ├── img68.png ├── img69.png ├── img7.png ├── img70.png ├── img71.png ├── img72.png ├── img73.png ├── img74.png ├── img75.png ├── img76.png ├── img77.png ├── img78.png ├── img79.png ├── img8.png ├── img80.png ├── img81.png ├── img82.png ├── img83.png ├── img84.png ├── img85.png ├── img86.png ├── img87.png ├── img88.png ├── img89.png ├── img9.png ├── img90.png ├── img91.png ├── img92.png ├── img93.png ├── img94.png ├── img95.png ├── img96.png ├── img97.png ├── img98.png └── img99.png ├── kernelized_sorting_bow.py ├── kernelized_sorting_color.py ├── main_bow.py ├── main_color.py ├── readme.md ├── requirements.txt ├── utils.py └── vector.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc -------------------------------------------------------------------------------- /documentation/output.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/documentation/output.jpg -------------------------------------------------------------------------------- /elefant_exceptions.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2007, National ICT Australia 2 | # All rights reserved. 3 | # 4 | # The contents of this file are subject to the Mozilla Public License Version 5 | # 1.1 (the 'License'); you may not use this file except in compliance with 6 | # the License. You may obtain a copy of the License at 7 | # http://www.mozilla.org/MPL/ 8 | # 9 | # Software distributed under the License is distributed on an 'AS IS' basis, 10 | # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 11 | # for the specific language governing rights and limitations under the 12 | # License. 13 | # 14 | # Authors: Christfried Webers 15 | # Created: (09/10/2007) 16 | # Last Updated: 17 | # 18 | 19 | ## Exception classes for the Elefant project 20 | 21 | class CElefantException(Exception): 22 | """Base class for exceptions in Elefant.""" 23 | pass 24 | 25 | 26 | class CElefantConstraintException(CElefantException): 27 | """Exception raised for constraint violation. 28 | 29 | Attributes: 30 | value -- input value violating constrained 31 | message -- explanation of the error 32 | """ 33 | 34 | def __init__(self, value, message): 35 | self.value = value 36 | self.message = message 37 | 38 | -------------------------------------------------------------------------------- /generic.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2006, National ICT Australia 2 | # All rights reserved. 3 | # 4 | # The contents of this file are subject to the Mozilla Public License Version 5 | # 1.1 (the "License"); you may not use this file except in compliance with 6 | # the License. You may obtain a copy of the License at 7 | # http://www.mozilla.org/MPL/ 8 | # 9 | # Software distributed under the License is distributed on an "AS IS" basis, 10 | # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 11 | # for the specific language governing rights and limitations under the 12 | # License. 13 | # 14 | # Authors: Le Song (lesong@it.usyd.edu.au) and Alex Smola 15 | # (alex.smola@nicta.com.au) 16 | # Created: (20/10/2006) 17 | # Last Updated: (dd/mm/yyyy) 18 | # 19 | 20 | ##\package elefant.kernels.generic 21 | # This module contains generic class for kernels 22 | # 23 | # The CKernel class provides common interface for all kernel classes. Note 24 | # that it should never be instantiated. 25 | # 26 | 27 | __version__ = "$Revision: $" 28 | # $Source$ 29 | 30 | import numpy 31 | import numpy.random as random 32 | 33 | ## Generic kernel class 34 | # 35 | # This kernel provide common interface for all kernels. This interface 36 | # includes the following key kernel manipulations (functions): 37 | # --Dot(x1, x2): $K(x1, x2)$ 38 | # --Expand(x1, x2, alpha): $sum_r K(x1_i,x2_r) \times alpha2_r$ 39 | # --Tensor(x1, y1, x2, y2): $K(x1_i,x2_j) \times (y1_i \times y1_j)$ 40 | # --TensorExpand(x1, y1, x2, y2, alpha2): 41 | # $sum_r K(x1_i,x2_r) \times (y1_i \times y1_r) \times alpha2_r$ 42 | # --Remember(x): Remember data x 43 | # --Forget(x): Remove remembered data x 44 | # To design a specific kernel, simply overload these methods. The generic 45 | # kernel itself should never be instantiated. 46 | # 47 | class CKernel(object): 48 | def __init__(self, blocksize=128): 49 | ## @var _blocksize 50 | # Parameter that determines the size of each block when computing the 51 | # kernel matrix in blocks. Properly blocking the kernel matrix during 52 | # computation improves the speed. 53 | # 54 | self._blocksize = blocksize 55 | ## @var _name 56 | # Name of the kernel. 57 | # 58 | self._name = "Generic kernel" 59 | ## @var _cacheData 60 | # Cache that stores data that have appeared before. 61 | # 62 | self._cacheData = {} 63 | 64 | def __str__(self): 65 | return self._name 66 | 67 | def __repr__(self): 68 | return "Kernel object of type '" + self._name + "'" 69 | 70 | ## Compute the kernel between two data points x1 and x2. 71 | # It returns a scale value of dot product between x1 and x2. 72 | # @param x1 [read] The first data point. 73 | # @param x2 [read] The second data point. 74 | # 75 | def K(self, x1, x2): 76 | raise NotImplementedError, \ 77 | 'CKernel.K in abstract class is not implemented' 78 | 79 | ## Compute the kernel between the data points in x1 and those in x2. 80 | # It returns a matrix with entry $(ij)$ equal to $K(x1_i, x1_j)$. 81 | # If index1/index2 is 82 | # specified, only those data points in x1/x2 with indices corresponding 83 | # to index1/index2 are used to compute the kernel matrix. Furthermore, 84 | # if output is specified, the provided buffer is used explicitly to 85 | # store the kernel matrix. 86 | # @param x1 [read] The first set of data points. 87 | # @param x2 [read] The second set of data points. 88 | # @param index1 [read] The indices into the first set of data points. 89 | # @param index2 [read] The indices into the second set of data points. 90 | # @param output [write] The buffer where the output matrix is written into. 91 | # 92 | def Dot(self, x1, x2, index1=None, index2=None, output=None): 93 | raise NotImplementedError, \ 94 | 'CKernel.Dot in abstract class is not implemented' 95 | 96 | ## Compute the kernel between the data points in x1 and those in x2, 97 | # then multiply the resulting kernel matrix by alpha2. 98 | # It returns a matrix with entry $(ij)$ equal to 99 | # $sum_r K(x1_i,x2_r) \times alpha2_r$. 100 | # Other parameters are defined similarly as those in Dot. 101 | # @param x1 [read] The first set of data points. 102 | # @param x2 [read] The second set of data points. 103 | # @param alpha2 [read] The set of coefficients. 104 | # @param index1 [read] The indices into the first set of data points. 105 | # @param index2 [read] The indices into the second set of data points. 106 | # @param output [write] The buffer where the output matrix is written into. 107 | # 108 | def Expand(self, x1, x2, alpha2, index1=None, index2=None, output=None): 109 | raise NotImplementedError, \ 110 | 'CKernel.Expand in abstract class is not implemented' 111 | 112 | ## Compute the kernel between the data points in x1 and those in x2, 113 | # then multiply the resulting kernel matrix elementwiesely by the 114 | # the outer-product matrix between y1 and y2. It returns a matrix 115 | # with entry $(ij)$ equal to $K(x1_i,x2_j) \times (y1_i \times y1_j)$. 116 | # Other parameters are defined similarly as those in Dot. 117 | # @param x1 [read] The first set of data points. 118 | # @param y1 [read] The first set of labels. 119 | # @param x2 [read] The second set of data points. 120 | # @param y2 [read] The second set of labels. 121 | # @param index1 [read] The indices into the first set of data points. 122 | # @param index2 [read] The indices into the second set of data points. 123 | # @param output [write] The buffer where the output matrix is written into. 124 | # 125 | def Tensor(self, x1, y1, x2, y2, index1=None, index2=None, output=None): 126 | raise NotImplementedError, \ 127 | 'CKernel.Tensor in abstract class is not implemented' 128 | 129 | ## Compute the kernel between the data points in x1 and those in x2, 130 | # then multiply the resulting kernel matrix elementwiesely by the 131 | # the outer-product matrix between y1 and y2, and final multiply 132 | # the resulting matrix by alpha2. It returns a matrix with entry $(ij)$ 133 | # equal to $sum_r K(x1_i,x2_r) \times (y1_i \times y1_r) \times alpha2_r$. 134 | # Other parameters are defined similarly as those in Dot. 135 | # @param x1 [read] The first set of data points. 136 | # @param y1 [read] The first set of labels. 137 | # @param x2 [read] The second set of data points. 138 | # @param y2 [read] The second set of labels. 139 | # @param index1 [read] The indices into the first set of data points. 140 | # @param index2 [read] The indices into the second set of data points. 141 | # @param output [write] The buffer where the output matrix is written into. 142 | # 143 | def TensorExpand(self, x1, y1, x2, y2, alpha2, index1=None, index2=None, \ 144 | output=None): 145 | raise NotImplementedError, \ 146 | 'CKernel.TensorExpand in abstract class is not implemented' 147 | 148 | ## Remember the data by performing necessary preprossing on 149 | # the data, storing it in the cache and indexing it by the id of 150 | # the data. The preprocessing can be defined differently for 151 | # different classes. If the data have already been remembered, 152 | # the old stored information is simply overwritten. 153 | # @param x [read] The data to be remembered. 154 | # 155 | def Remember(self, x): 156 | raise NotImplementedError, \ 157 | 'CKernel.Remember in abstract class is not implemented' 158 | 159 | ## Remove a remembered data from the cache. If x is not given, then 160 | # all the data remembered in the cache will be removed. If a given 161 | # x is not remembered beforehand, False is returned; otherwise, True 162 | # is returned. 163 | # @param x [read] The data to be removed. 164 | # 165 | def Forget(self, x=None): 166 | raise NotImplementedError, \ 167 | 'CKernel.Forget in abstract class is not implemented' 168 | 169 | -------------------------------------------------------------------------------- /images/img1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img1.png -------------------------------------------------------------------------------- /images/img10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img10.png -------------------------------------------------------------------------------- /images/img100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img100.png -------------------------------------------------------------------------------- /images/img101.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img101.png -------------------------------------------------------------------------------- /images/img102.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img102.png -------------------------------------------------------------------------------- /images/img103.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img103.png -------------------------------------------------------------------------------- /images/img104.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img104.png -------------------------------------------------------------------------------- /images/img105.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img105.png -------------------------------------------------------------------------------- /images/img106.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img106.png -------------------------------------------------------------------------------- /images/img107.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img107.png -------------------------------------------------------------------------------- /images/img108.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img108.png -------------------------------------------------------------------------------- /images/img109.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img109.png -------------------------------------------------------------------------------- /images/img11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img11.png -------------------------------------------------------------------------------- /images/img110.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img110.png -------------------------------------------------------------------------------- /images/img111.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img111.png -------------------------------------------------------------------------------- /images/img112.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img112.png -------------------------------------------------------------------------------- /images/img113.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img113.png -------------------------------------------------------------------------------- /images/img114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img114.png -------------------------------------------------------------------------------- /images/img115.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img115.png -------------------------------------------------------------------------------- /images/img116.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img116.png -------------------------------------------------------------------------------- /images/img117.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img117.png -------------------------------------------------------------------------------- /images/img118.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img118.png -------------------------------------------------------------------------------- /images/img119.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img119.png -------------------------------------------------------------------------------- /images/img12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img12.png -------------------------------------------------------------------------------- /images/img120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img120.png -------------------------------------------------------------------------------- /images/img121.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img121.png -------------------------------------------------------------------------------- /images/img122.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img122.png -------------------------------------------------------------------------------- /images/img123.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img123.png -------------------------------------------------------------------------------- /images/img124.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img124.png -------------------------------------------------------------------------------- /images/img125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img125.png -------------------------------------------------------------------------------- /images/img126.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img126.png -------------------------------------------------------------------------------- /images/img127.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img127.png -------------------------------------------------------------------------------- /images/img128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img128.png -------------------------------------------------------------------------------- /images/img129.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img129.png -------------------------------------------------------------------------------- /images/img13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img13.png -------------------------------------------------------------------------------- /images/img130.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img130.png -------------------------------------------------------------------------------- /images/img131.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img131.png -------------------------------------------------------------------------------- /images/img132.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img132.png -------------------------------------------------------------------------------- /images/img133.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img133.png -------------------------------------------------------------------------------- /images/img134.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img134.png -------------------------------------------------------------------------------- /images/img135.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img135.png -------------------------------------------------------------------------------- /images/img136.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img136.png -------------------------------------------------------------------------------- /images/img137.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img137.png -------------------------------------------------------------------------------- /images/img138.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img138.png -------------------------------------------------------------------------------- /images/img139.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img139.png -------------------------------------------------------------------------------- /images/img14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img14.png -------------------------------------------------------------------------------- /images/img140.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img140.png -------------------------------------------------------------------------------- /images/img141.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img141.png -------------------------------------------------------------------------------- /images/img142.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img142.png -------------------------------------------------------------------------------- /images/img143.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img143.png -------------------------------------------------------------------------------- /images/img144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img144.png -------------------------------------------------------------------------------- /images/img145.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img145.png -------------------------------------------------------------------------------- /images/img146.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img146.png -------------------------------------------------------------------------------- /images/img147.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img147.png -------------------------------------------------------------------------------- /images/img148.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img148.png -------------------------------------------------------------------------------- /images/img149.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img149.png -------------------------------------------------------------------------------- /images/img15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img15.png -------------------------------------------------------------------------------- /images/img150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img150.png -------------------------------------------------------------------------------- /images/img151.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img151.png -------------------------------------------------------------------------------- /images/img152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img152.png -------------------------------------------------------------------------------- /images/img153.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img153.png -------------------------------------------------------------------------------- /images/img154.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img154.png -------------------------------------------------------------------------------- /images/img155.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img155.png -------------------------------------------------------------------------------- /images/img156.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img156.png -------------------------------------------------------------------------------- /images/img157.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img157.png -------------------------------------------------------------------------------- /images/img158.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img158.png -------------------------------------------------------------------------------- /images/img159.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img159.png -------------------------------------------------------------------------------- /images/img16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img16.png -------------------------------------------------------------------------------- /images/img160.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img160.png -------------------------------------------------------------------------------- /images/img161.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img161.png -------------------------------------------------------------------------------- /images/img162.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img162.png -------------------------------------------------------------------------------- /images/img163.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img163.png -------------------------------------------------------------------------------- /images/img164.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img164.png -------------------------------------------------------------------------------- /images/img165.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img165.png -------------------------------------------------------------------------------- /images/img166.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img166.png -------------------------------------------------------------------------------- /images/img167.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img167.png -------------------------------------------------------------------------------- /images/img168.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img168.png -------------------------------------------------------------------------------- /images/img169.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img169.png -------------------------------------------------------------------------------- /images/img17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img17.png -------------------------------------------------------------------------------- /images/img170.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img170.png -------------------------------------------------------------------------------- /images/img171.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img171.png -------------------------------------------------------------------------------- /images/img172.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img172.png -------------------------------------------------------------------------------- /images/img173.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img173.png -------------------------------------------------------------------------------- /images/img174.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img174.png -------------------------------------------------------------------------------- /images/img175.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img175.png -------------------------------------------------------------------------------- /images/img176.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img176.png -------------------------------------------------------------------------------- /images/img177.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img177.png -------------------------------------------------------------------------------- /images/img178.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img178.png -------------------------------------------------------------------------------- /images/img179.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img179.png -------------------------------------------------------------------------------- /images/img18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img18.png -------------------------------------------------------------------------------- /images/img180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img180.png -------------------------------------------------------------------------------- /images/img181.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img181.png -------------------------------------------------------------------------------- /images/img182.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img182.png -------------------------------------------------------------------------------- /images/img183.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img183.png -------------------------------------------------------------------------------- /images/img184.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img184.png -------------------------------------------------------------------------------- /images/img185.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img185.png -------------------------------------------------------------------------------- /images/img186.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img186.png -------------------------------------------------------------------------------- /images/img187.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img187.png -------------------------------------------------------------------------------- /images/img188.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img188.png -------------------------------------------------------------------------------- /images/img189.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img189.png -------------------------------------------------------------------------------- /images/img19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img19.png -------------------------------------------------------------------------------- /images/img190.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img190.png -------------------------------------------------------------------------------- /images/img191.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img191.png -------------------------------------------------------------------------------- /images/img192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img192.png -------------------------------------------------------------------------------- /images/img193.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img193.png -------------------------------------------------------------------------------- /images/img194.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img194.png -------------------------------------------------------------------------------- /images/img195.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img195.png -------------------------------------------------------------------------------- /images/img196.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img196.png -------------------------------------------------------------------------------- /images/img197.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img197.png -------------------------------------------------------------------------------- /images/img198.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img198.png -------------------------------------------------------------------------------- /images/img199.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img199.png -------------------------------------------------------------------------------- /images/img2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img2.png -------------------------------------------------------------------------------- /images/img20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img20.png -------------------------------------------------------------------------------- /images/img200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img200.png -------------------------------------------------------------------------------- /images/img201.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img201.png -------------------------------------------------------------------------------- /images/img202.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img202.png -------------------------------------------------------------------------------- /images/img203.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img203.png -------------------------------------------------------------------------------- /images/img204.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img204.png -------------------------------------------------------------------------------- /images/img205.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img205.png -------------------------------------------------------------------------------- /images/img206.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img206.png -------------------------------------------------------------------------------- /images/img207.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img207.png -------------------------------------------------------------------------------- /images/img208.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img208.png -------------------------------------------------------------------------------- /images/img209.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img209.png -------------------------------------------------------------------------------- /images/img21.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img21.png -------------------------------------------------------------------------------- /images/img210.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img210.png -------------------------------------------------------------------------------- /images/img211.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img211.png -------------------------------------------------------------------------------- /images/img212.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img212.png -------------------------------------------------------------------------------- /images/img213.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img213.png -------------------------------------------------------------------------------- /images/img214.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img214.png -------------------------------------------------------------------------------- /images/img215.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img215.png -------------------------------------------------------------------------------- /images/img216.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img216.png -------------------------------------------------------------------------------- /images/img217.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img217.png -------------------------------------------------------------------------------- /images/img218.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img218.png -------------------------------------------------------------------------------- /images/img219.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img219.png -------------------------------------------------------------------------------- /images/img22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img22.png -------------------------------------------------------------------------------- /images/img220.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img220.png -------------------------------------------------------------------------------- /images/img221.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img221.png -------------------------------------------------------------------------------- /images/img222.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img222.png -------------------------------------------------------------------------------- /images/img223.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img223.png -------------------------------------------------------------------------------- /images/img224.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img224.png -------------------------------------------------------------------------------- /images/img225.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img225.png -------------------------------------------------------------------------------- /images/img226.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img226.png -------------------------------------------------------------------------------- /images/img227.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img227.png -------------------------------------------------------------------------------- /images/img228.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img228.png -------------------------------------------------------------------------------- /images/img229.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img229.png -------------------------------------------------------------------------------- /images/img23.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img23.png -------------------------------------------------------------------------------- /images/img230.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img230.png -------------------------------------------------------------------------------- /images/img231.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img231.png -------------------------------------------------------------------------------- /images/img232.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img232.png -------------------------------------------------------------------------------- /images/img233.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img233.png -------------------------------------------------------------------------------- /images/img234.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img234.png -------------------------------------------------------------------------------- /images/img235.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img235.png -------------------------------------------------------------------------------- /images/img236.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img236.png -------------------------------------------------------------------------------- /images/img237.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img237.png -------------------------------------------------------------------------------- /images/img238.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img238.png -------------------------------------------------------------------------------- /images/img239.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img239.png -------------------------------------------------------------------------------- /images/img24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img24.png -------------------------------------------------------------------------------- /images/img240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img240.png -------------------------------------------------------------------------------- /images/img241.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img241.png -------------------------------------------------------------------------------- /images/img242.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img242.png -------------------------------------------------------------------------------- /images/img243.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img243.png -------------------------------------------------------------------------------- /images/img244.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img244.png -------------------------------------------------------------------------------- /images/img245.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img245.png -------------------------------------------------------------------------------- /images/img246.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img246.png -------------------------------------------------------------------------------- /images/img247.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img247.png -------------------------------------------------------------------------------- /images/img248.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img248.png -------------------------------------------------------------------------------- /images/img249.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img249.png -------------------------------------------------------------------------------- /images/img25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img25.png -------------------------------------------------------------------------------- /images/img250.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img250.png -------------------------------------------------------------------------------- /images/img251.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img251.png -------------------------------------------------------------------------------- /images/img252.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img252.png -------------------------------------------------------------------------------- /images/img253.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img253.png -------------------------------------------------------------------------------- /images/img254.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img254.png -------------------------------------------------------------------------------- /images/img255.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img255.png -------------------------------------------------------------------------------- /images/img256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img256.png -------------------------------------------------------------------------------- /images/img257.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img257.png -------------------------------------------------------------------------------- /images/img258.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img258.png -------------------------------------------------------------------------------- /images/img259.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img259.png -------------------------------------------------------------------------------- /images/img26.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img26.png -------------------------------------------------------------------------------- /images/img260.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img260.png -------------------------------------------------------------------------------- /images/img261.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img261.png -------------------------------------------------------------------------------- /images/img262.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img262.png -------------------------------------------------------------------------------- /images/img263.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img263.png -------------------------------------------------------------------------------- /images/img264.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img264.png -------------------------------------------------------------------------------- /images/img265.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img265.png -------------------------------------------------------------------------------- /images/img266.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img266.png -------------------------------------------------------------------------------- /images/img267.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img267.png -------------------------------------------------------------------------------- /images/img268.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img268.png -------------------------------------------------------------------------------- /images/img269.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img269.png -------------------------------------------------------------------------------- /images/img27.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img27.png -------------------------------------------------------------------------------- /images/img270.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img270.png -------------------------------------------------------------------------------- /images/img271.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img271.png -------------------------------------------------------------------------------- /images/img272.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img272.png -------------------------------------------------------------------------------- /images/img273.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img273.png -------------------------------------------------------------------------------- /images/img274.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img274.png -------------------------------------------------------------------------------- /images/img275.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img275.png -------------------------------------------------------------------------------- /images/img276.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img276.png -------------------------------------------------------------------------------- /images/img277.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img277.png -------------------------------------------------------------------------------- /images/img278.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img278.png -------------------------------------------------------------------------------- /images/img279.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img279.png -------------------------------------------------------------------------------- /images/img28.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img28.png -------------------------------------------------------------------------------- /images/img280.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img280.png -------------------------------------------------------------------------------- /images/img281.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img281.png -------------------------------------------------------------------------------- /images/img282.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img282.png -------------------------------------------------------------------------------- /images/img283.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img283.png -------------------------------------------------------------------------------- /images/img284.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img284.png -------------------------------------------------------------------------------- /images/img285.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img285.png -------------------------------------------------------------------------------- /images/img286.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img286.png -------------------------------------------------------------------------------- /images/img287.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img287.png -------------------------------------------------------------------------------- /images/img288.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img288.png -------------------------------------------------------------------------------- /images/img289.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img289.png -------------------------------------------------------------------------------- /images/img29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img29.png -------------------------------------------------------------------------------- /images/img290.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img290.png -------------------------------------------------------------------------------- /images/img291.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img291.png -------------------------------------------------------------------------------- /images/img292.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img292.png -------------------------------------------------------------------------------- /images/img293.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img293.png -------------------------------------------------------------------------------- /images/img294.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img294.png -------------------------------------------------------------------------------- /images/img295.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img295.png -------------------------------------------------------------------------------- /images/img296.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img296.png -------------------------------------------------------------------------------- /images/img297.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img297.png -------------------------------------------------------------------------------- /images/img298.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img298.png -------------------------------------------------------------------------------- /images/img299.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img299.png -------------------------------------------------------------------------------- /images/img3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img3.png -------------------------------------------------------------------------------- /images/img30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img30.png -------------------------------------------------------------------------------- /images/img300.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img300.png -------------------------------------------------------------------------------- /images/img301.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img301.png -------------------------------------------------------------------------------- /images/img302.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img302.png -------------------------------------------------------------------------------- /images/img303.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img303.png -------------------------------------------------------------------------------- /images/img304.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img304.png -------------------------------------------------------------------------------- /images/img305.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img305.png -------------------------------------------------------------------------------- /images/img306.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img306.png -------------------------------------------------------------------------------- /images/img307.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img307.png -------------------------------------------------------------------------------- /images/img308.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img308.png -------------------------------------------------------------------------------- /images/img309.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img309.png -------------------------------------------------------------------------------- /images/img31.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img31.png -------------------------------------------------------------------------------- /images/img310.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img310.png -------------------------------------------------------------------------------- /images/img311.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img311.png -------------------------------------------------------------------------------- /images/img312.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img312.png -------------------------------------------------------------------------------- /images/img313.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img313.png -------------------------------------------------------------------------------- /images/img314.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img314.png -------------------------------------------------------------------------------- /images/img315.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img315.png -------------------------------------------------------------------------------- /images/img316.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img316.png -------------------------------------------------------------------------------- /images/img317.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img317.png -------------------------------------------------------------------------------- /images/img318.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img318.png -------------------------------------------------------------------------------- /images/img319.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img319.png -------------------------------------------------------------------------------- /images/img32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img32.png -------------------------------------------------------------------------------- /images/img320.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img320.png -------------------------------------------------------------------------------- /images/img33.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img33.png -------------------------------------------------------------------------------- /images/img34.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img34.png -------------------------------------------------------------------------------- /images/img35.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img35.png -------------------------------------------------------------------------------- /images/img36.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img36.png -------------------------------------------------------------------------------- /images/img37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img37.png -------------------------------------------------------------------------------- /images/img38.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img38.png -------------------------------------------------------------------------------- /images/img39.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img39.png -------------------------------------------------------------------------------- /images/img4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img4.png -------------------------------------------------------------------------------- /images/img40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img40.png -------------------------------------------------------------------------------- /images/img41.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img41.png -------------------------------------------------------------------------------- /images/img42.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img42.png -------------------------------------------------------------------------------- /images/img43.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img43.png -------------------------------------------------------------------------------- /images/img44.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img44.png -------------------------------------------------------------------------------- /images/img45.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img45.png -------------------------------------------------------------------------------- /images/img46.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img46.png -------------------------------------------------------------------------------- /images/img47.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img47.png -------------------------------------------------------------------------------- /images/img48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img48.png -------------------------------------------------------------------------------- /images/img49.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img49.png -------------------------------------------------------------------------------- /images/img5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img5.png -------------------------------------------------------------------------------- /images/img50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img50.png -------------------------------------------------------------------------------- /images/img51.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img51.png -------------------------------------------------------------------------------- /images/img52.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img52.png -------------------------------------------------------------------------------- /images/img53.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img53.png -------------------------------------------------------------------------------- /images/img54.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img54.png -------------------------------------------------------------------------------- /images/img55.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img55.png -------------------------------------------------------------------------------- /images/img56.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img56.png -------------------------------------------------------------------------------- /images/img57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img57.png -------------------------------------------------------------------------------- /images/img58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img58.png -------------------------------------------------------------------------------- /images/img59.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img59.png -------------------------------------------------------------------------------- /images/img6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img6.png -------------------------------------------------------------------------------- /images/img60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img60.png -------------------------------------------------------------------------------- /images/img61.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img61.png -------------------------------------------------------------------------------- /images/img62.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img62.png -------------------------------------------------------------------------------- /images/img63.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img63.png -------------------------------------------------------------------------------- /images/img64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img64.png -------------------------------------------------------------------------------- /images/img65.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img65.png -------------------------------------------------------------------------------- /images/img66.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img66.png -------------------------------------------------------------------------------- /images/img67.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img67.png -------------------------------------------------------------------------------- /images/img68.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img68.png -------------------------------------------------------------------------------- /images/img69.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img69.png -------------------------------------------------------------------------------- /images/img7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img7.png -------------------------------------------------------------------------------- /images/img70.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img70.png -------------------------------------------------------------------------------- /images/img71.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img71.png -------------------------------------------------------------------------------- /images/img72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img72.png -------------------------------------------------------------------------------- /images/img73.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img73.png -------------------------------------------------------------------------------- /images/img74.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img74.png -------------------------------------------------------------------------------- /images/img75.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img75.png -------------------------------------------------------------------------------- /images/img76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img76.png -------------------------------------------------------------------------------- /images/img77.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img77.png -------------------------------------------------------------------------------- /images/img78.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img78.png -------------------------------------------------------------------------------- /images/img79.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img79.png -------------------------------------------------------------------------------- /images/img8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img8.png -------------------------------------------------------------------------------- /images/img80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img80.png -------------------------------------------------------------------------------- /images/img81.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img81.png -------------------------------------------------------------------------------- /images/img82.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img82.png -------------------------------------------------------------------------------- /images/img83.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img83.png -------------------------------------------------------------------------------- /images/img84.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img84.png -------------------------------------------------------------------------------- /images/img85.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img85.png -------------------------------------------------------------------------------- /images/img86.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img86.png -------------------------------------------------------------------------------- /images/img87.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img87.png -------------------------------------------------------------------------------- /images/img88.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img88.png -------------------------------------------------------------------------------- /images/img89.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img89.png -------------------------------------------------------------------------------- /images/img9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img9.png -------------------------------------------------------------------------------- /images/img90.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img90.png -------------------------------------------------------------------------------- /images/img91.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img91.png -------------------------------------------------------------------------------- /images/img92.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img92.png -------------------------------------------------------------------------------- /images/img93.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img93.png -------------------------------------------------------------------------------- /images/img94.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img94.png -------------------------------------------------------------------------------- /images/img95.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img95.png -------------------------------------------------------------------------------- /images/img96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img96.png -------------------------------------------------------------------------------- /images/img97.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img97.png -------------------------------------------------------------------------------- /images/img98.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img98.png -------------------------------------------------------------------------------- /images/img99.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kylemcdonald/KernelizedSorting/1fe7d56b484456a8191ba4ced4c559f9e9679dec/images/img99.png -------------------------------------------------------------------------------- /kernelized_sorting_bow.py: -------------------------------------------------------------------------------- 1 | import warnings 2 | import exceptions 3 | import sys 4 | import matplotlib.pylab as mp 5 | import time 6 | import numpy 7 | import numpy as np 8 | from vector import CGaussKernel,CLinearKernel,CRBFKernel 9 | from numpy.random import randn,rand 10 | import hungarian #,LAPJV # LAP solvers 11 | import pdb 12 | np.seterr(divide='ignore', invalid='ignore') 13 | 14 | def KS(X_1,X_2): 15 | init_type = 'eig' # random, eig, ... 16 | llambda = 1.0 # step size 17 | n_iter = 100 # number of LAP iterations 18 | omegas = 2.0 19 | n_obs = X_1.shape[0] # number of observations 20 | bases = numpy.eye(n_obs) 21 | # normalization of data 22 | l2norm = numpy.zeros((n_obs,1)) 23 | for i in xrange(n_obs): 24 | l2norm[i] = numpy.sum(X_1[i,]) 25 | new_X_1 = X_1/l2norm 26 | 27 | starttime = time.clock() 28 | # kernel for grid 29 | dl = CRBFKernel(); 30 | dL = dl.Dot(X_2, X_2) 31 | omega_L = 1.0 / numpy.median(dL.flatten()) 32 | kernel_L = CGaussKernel(omega_L) 33 | L = kernel_L.Dot(X_2,X_2) # should use incomplete cholesky instead ... 34 | # kernel for data 35 | tK = numpy.zeros((n_obs,n_obs)) 36 | for i in xrange(n_obs): 37 | for j in xrange(i,n_obs): 38 | temp = ((new_X_1[i,:]-new_X_1[j,:])**2)/(new_X_1[i,:]+new_X_1[j,:]) 39 | inan = numpy.isnan(temp) 40 | temp[inan] = 0.0 41 | tK[i,j] = tK[j,i] = numpy.sum(temp)*0.5 42 | mdisK = numpy.median(numpy.median(tK)) 43 | K = numpy.zeros((n_obs,n_obs)) 44 | for i in xrange(n_obs): 45 | for j in xrange (i,n_obs): 46 | temp = ((new_X_1[i,:]-new_X_1[j,:])**2)/(new_X_1[i,:]+new_X_1[j,:]) 47 | inan = numpy.isnan(temp) 48 | temp[inan] = 0.0 49 | K[i,j] = K [j,i] = numpy.exp(-1.0*omegas/mdisK*numpy.sum(temp)*0.5) #chi-square kernel 50 | 51 | stoptime = time.clock() 52 | print 'computing kernel matrices (K and L) takes %f seconds '% (stoptime-starttime) 53 | 54 | print 'original objective function : ' 55 | H = numpy.eye(n_obs) - numpy.ones(n_obs)/n_obs 56 | print numpy.trace(numpy.dot(numpy.dot(numpy.dot(H,K),H),L)) 57 | 58 | # initializing the permutation matrix 59 | if (cmp(init_type,'random') == 0): 60 | print 'random initialization is being used ... \n' 61 | PI_0 = init_random(n_obs) 62 | elif (cmp(init_type,'eig') == 0): 63 | print 'sorted eigenvector initialization is being used ... \n' 64 | PI_0 = init_eig(K,L,n_obs) 65 | else: 66 | print 'wrong initialization type ... ' 67 | 68 | # centering of kernel matrices 69 | H = numpy.eye(n_obs) - numpy.ones(n_obs)/n_obs 70 | K = numpy.dot(H,numpy.dot(K,H)) 71 | L = numpy.dot(H,numpy.dot(L,H)) 72 | 73 | print 'initial objective: ' 74 | print numpy.trace(numpy.dot(numpy.dot(numpy.dot(PI_0,K),PI_0.T),L)) 75 | 76 | # iterative linear assignment solution 77 | PI_t = numpy.zeros((n_obs,n_obs)) 78 | for i in xrange(n_iter): 79 | print 'iteration : ',i 80 | starttime = time.clock() 81 | grad = compute_gradient(K,L,PI_0) # L * P_0 * K 82 | stoptime = time.clock() 83 | print 'computing gradient takes %f seconds '% (stoptime-starttime) 84 | 85 | # convert grad (profit matrix) to cost matrix 86 | # assuming it is a finite cost problem, thus 87 | # all the elements are substracted from the max value of the whole matrix 88 | cost_matrix = -grad 89 | starttime = time.clock() 90 | #indexes = LAPJV.lap(cost_matrix)[1] 91 | indexes = hungarian.hungarian(cost_matrix)[0] 92 | indexes = numpy.array(indexes) 93 | 94 | stoptime = time.clock() 95 | print 'lap solver takes %f seconds '% (stoptime-starttime) 96 | 97 | PI_t = numpy.eye(n_obs) 98 | PI_t = PI_t[indexes,] 99 | 100 | # convex combination 101 | PI = (1-llambda)*PI_0 + (llambda)*PI_t 102 | # gradient ascent 103 | #PI = PI_0 + llambda*compute_gradient(K,L,PI_t) 104 | 105 | # computing the objective function 106 | obj_funct = numpy.trace(numpy.dot(numpy.dot(numpy.dot(PI_t,K),PI_t.T),L)) 107 | print 'objective function value : ',obj_funct 108 | print '\n' 109 | 110 | # another termination criteria 111 | if (numpy.trace(numpy.dot(numpy.dot(numpy.dot(PI,K),PI.T),L)) - numpy.trace(numpy.dot(numpy.dot(numpy.dot(PI_0,K),PI_0.T),L)) <= 1e-5): 112 | PI_final = PI_t 113 | break 114 | 115 | PI_0 = PI 116 | if (i == n_iter-1): 117 | PI_final = PI_t 118 | 119 | return PI_final 120 | def compute_gradient(K,L,PI_0): 121 | grad = numpy.dot(L,numpy.dot(PI_0,K)) 122 | grad = 2*grad 123 | return grad 124 | 125 | def init_eig(K,L,n_obs): 126 | # with sorted eigenvectors 127 | [U_K,V_K] = numpy.linalg.eig(K) 128 | [U_L,V_L] = numpy.linalg.eig(L) 129 | i_VK = numpy.argsort(-V_K[:,0]) 130 | i_VL = numpy.argsort(-V_L[:,0]) 131 | PI_0 = numpy.zeros((n_obs,n_obs)) 132 | PI_0[numpy.array(i_VL),numpy.array(i_VK)] = 1 133 | return PI_0 134 | 135 | def init_random(n_obs): 136 | # random initialization 137 | bases = numpy.eye(n_obs) 138 | init = numpy.random.permutation(n_obs) 139 | PI_0 = bases[init,:] 140 | return PI_0 141 | 142 | 143 | if __name__=='__main__': 144 | main() -------------------------------------------------------------------------------- /kernelized_sorting_color.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import matplotlib.pylab as mp 3 | import time 4 | import numpy 5 | import numpy as np 6 | from vector import CGaussKernel,CLinearKernel,CRBFKernel 7 | from numpy.random import randn,rand 8 | import hungarian #,LAPJV # LAP solvers 9 | import lapjv 10 | import pdb 11 | 12 | def KS(X_1,X_2): 13 | init_type = 'eig' # random, eig, ... 14 | omegas = 1.0 15 | llambda = 1.0 # step size 16 | n_iter = 100 # number of LAP iterations 17 | n_obs = X_1.shape[0] # number of observations 18 | bases = numpy.eye(n_obs) 19 | 20 | # compute the kernel matrix 21 | starttime = time.clock() 22 | dk = CRBFKernel(); 23 | dl = CRBFKernel(); 24 | dK = dk.Dot(X_1, X_1) 25 | dL = dl.Dot(X_2, X_2) 26 | omega_K = 1.0*omegas / numpy.median(dK.flatten()) 27 | omega_L = 1.0 / numpy.median(dL.flatten()) 28 | 29 | kernel_K = CGaussKernel(omega_K) 30 | kernel_L = CGaussKernel(omega_L) 31 | 32 | K = kernel_K.Dot(X_1,X_1) # should use incomplete cholesky instead ... 33 | L = kernel_L.Dot(X_2,X_2) # should use incomplete cholesky instead ... 34 | 35 | stoptime = time.clock() 36 | print 'computing kernel matrices (K and L) takes %f seconds '% (stoptime-starttime) 37 | 38 | print 'original objective function : ' 39 | H = numpy.eye(n_obs) - numpy.ones(n_obs)/n_obs 40 | print numpy.trace(numpy.dot(numpy.dot(numpy.dot(H,K),H),L)) 41 | 42 | # initializing the permutation matrix 43 | if (cmp(init_type,'random') == 0): 44 | print 'random initialization is being used ... \n' 45 | PI_0 = init_random(n_obs) 46 | elif (cmp(init_type,'eig') == 0): 47 | print 'sorted eigenvector initialization is being used ... \n' 48 | PI_0 = init_eig(K,L,n_obs) 49 | else: 50 | print 'wrong initialization type ... ' 51 | 52 | # centering of kernel matrices 53 | H = numpy.eye(n_obs) - numpy.ones(n_obs)/n_obs 54 | K = numpy.dot(H,numpy.dot(K,H)) 55 | L = numpy.dot(H,numpy.dot(L,H)) 56 | 57 | print 'initial objective: ' 58 | print numpy.trace(numpy.dot(numpy.dot(numpy.dot(PI_0,K),PI_0.T),L)) 59 | 60 | 61 | # iterative linear assignment solution 62 | PI_t = numpy.zeros((n_obs,n_obs)) 63 | for i in xrange(n_iter): 64 | print 'iteration : ',i 65 | starttime = time.clock() 66 | grad = compute_gradient(K,L,PI_0) # L * P_0 * K 67 | stoptime = time.clock() 68 | print 'computing gradient takes %f seconds '% (stoptime-starttime) 69 | 70 | # convert grad (profit matrix) to cost matrix 71 | # assuming it is a finite cost problem, thus 72 | # all the elements are substracted from the max value of the whole matrix 73 | cost_matrix = -grad 74 | starttime = time.clock() 75 | print 'solving cost_matrix with shape {}'.format(cost_matrix.shape) 76 | # indexes = lapjv.lapjv(cost_matrix)[1] 77 | indexes = hungarian.lap(cost_matrix)[0] 78 | indexes = numpy.array(indexes) 79 | 80 | stoptime = time.clock() 81 | print 'lap solver takes %f seconds '% (stoptime-starttime) 82 | 83 | PI_t = numpy.eye(n_obs) 84 | PI_t = PI_t[indexes,] 85 | 86 | # convex combination 87 | PI = (1-llambda)*PI_0 + (llambda)*PI_t 88 | # gradient ascent 89 | #PI = PI_0 + llambda*compute_gradient(K,L,PI_t) 90 | 91 | # computing the objective function 92 | obj_funct = numpy.trace(numpy.dot(numpy.dot(numpy.dot(PI_t,K),PI_t.T),L)) 93 | print 'objective function value : ',obj_funct 94 | print '\n' 95 | 96 | # another termination criteria 97 | if (numpy.trace(numpy.dot(numpy.dot(numpy.dot(PI,K),PI.T),L)) - numpy.trace(numpy.dot(numpy.dot(numpy.dot(PI_0,K),PI_0.T),L)) <= 1e-5): 98 | PI_final = PI_t 99 | break 100 | 101 | PI_0 = PI 102 | if (i == n_iter-1): 103 | PI_final = PI_t 104 | 105 | return PI_final 106 | def compute_gradient(K,L,PI_0): 107 | grad = numpy.dot(L,numpy.dot(PI_0,K)) 108 | grad = 2*grad 109 | return grad 110 | 111 | def init_eig(K,L,n_obs): 112 | # with sorted eigenvectors 113 | [U_K,V_K] = numpy.linalg.eig(K) 114 | [U_L,V_L] = numpy.linalg.eig(L) 115 | i_VK = numpy.argsort(-V_K[:,0]) 116 | i_VL = numpy.argsort(-V_L[:,0]) 117 | PI_0 = numpy.zeros((n_obs,n_obs)) 118 | PI_0[numpy.array(i_VL),numpy.array(i_VK)] = 1 119 | return PI_0 120 | 121 | def init_random(n_obs): 122 | # random initialization 123 | bases = numpy.eye(n_obs) 124 | init = numpy.random.permutation(n_obs) 125 | PI_0 = bases[init,:] 126 | return PI_0 127 | 128 | 129 | if __name__=='__main__': 130 | main() -------------------------------------------------------------------------------- /main_bow.py: -------------------------------------------------------------------------------- 1 | ## Kernelized Sorting for Image Layouting with bag-of-words features 2 | ## param[in] psize sampling size of image 3 | ## param[in] ino width of the layout area 4 | ## param[in] jno height of the layout area 5 | ## param[in] iname file name for the images 6 | ## param[in] bname file name for the bow files 7 | 8 | from kernelized_sorting_bow import KS 9 | from utils import lab 10 | import matplotlib.pylab as mp 11 | import Image 12 | import numpy 13 | import pdb 14 | 15 | ino = 25 16 | jno = 25 17 | psize = 200 18 | iname = 'PPMImages/' 19 | bname = 'OlympicGames_bows/' 20 | 21 | n_image = ino*jno 22 | imgdata = [] 23 | data = [] 24 | counter = 0 25 | for i in xrange(n_image): 26 | counter = counter + 1 27 | fname = iname + str(counter) + '.jpg' 28 | im = Image.open(fname) 29 | aim = numpy.asarray(im) 30 | [M,N,L] = aim.shape 31 | mno = numpy.fix(M/psize) 32 | nno = numpy.fix(N/psize) 33 | aim = aim[0:psize*mno:mno,0:psize*nno:nno,:] 34 | data.append(aim.flatten()) #images 35 | fname = bname + str(counter) + '.bow' 36 | lines = open(fname).readlines() 37 | temp = [] 38 | tokens = lines[0].split() 39 | for i in xrange(len(tokens)): 40 | temp.append(eval(tokens[i])) 41 | temp = numpy.array(temp) 42 | imgdata.append(temp.flatten()) #its corresponding bow (bag-of-words features) 43 | 44 | data = numpy.array(data) 45 | imgdata = numpy.array(imgdata) 46 | griddata = numpy.zeros((2,ino*jno)) 47 | griddata[0,] = numpy.kron(range(1,ino+1),numpy.ones((1,jno))) 48 | griddata[1,] = numpy.tile(range(1,jno+1),(1,ino)) 49 | 50 | # do kernelized sorting procedure 51 | PI = KS(imgdata,griddata.T) 52 | i_sorting = PI.argmax(axis=1) 53 | imgdata_sorted = data[i_sorting,] 54 | irange = range(0,psize*ino,psize) 55 | jrange = range(0,psize*jno,psize) 56 | patching = numpy.zeros((ino*psize, jno*psize, 3)) 57 | for i in xrange(ino): 58 | for j in xrange(jno): 59 | patching[irange[i]:irange[i]+psize,jrange[j]:jrange[j]+psize,:] = numpy.reshape(imgdata_sorted[(i)*jno+j,], [psize,psize,3]); 60 | 61 | im = Image.fromarray(patching.astype(numpy.uint8)) 62 | im.show() 63 | -------------------------------------------------------------------------------- /main_color.py: -------------------------------------------------------------------------------- 1 | from kernelized_sorting_color import KS 2 | from utils import * 3 | import matplotlib.pylab as mp 4 | from PIL import Image 5 | import numpy as np 6 | import argparse 7 | 8 | parser = argparse.ArgumentParser( 9 | description='Kernelized Sorting for Image Layouting with color features.') 10 | parser.add_argument('-s', '--image_size', 11 | type=int, 12 | default=40, 13 | help='Size of the side each tile.') 14 | parser.add_argument('-i', '--input_directory', 15 | type=str, 16 | default='images', 17 | help='Directory containing images.') 18 | parser.add_argument('-o', '--output_filename', 19 | type=str, 20 | default='output.png', 21 | help='Output filename.') 22 | parser.add_argument('-n', 23 | type=int, 24 | default=None, 25 | help='Number of tiles along x axis.') 26 | args = parser.parse_args() 27 | 28 | nx = args.n 29 | psize = args.image_size 30 | iname = args.input_directory 31 | oname = args.output_filename 32 | 33 | filenames = list(list_all_files(iname, ['.png', '.jpg'])) 34 | n = len(filenames) 35 | if nx is None: 36 | nx, ny = find_rectangle(n) 37 | else: 38 | ny = n / nx 39 | print('Using {}x{} tiles.'.format(nx, ny)) 40 | 41 | print('Resizing images...') 42 | imgdata = [] 43 | data = [] 44 | for fn in filenames: 45 | im = Image.open(fn) 46 | w, h = im.size 47 | hw, hh = (w/2, h/2) 48 | hs = min(hw, hh) 49 | box = (hw - hs, hh - hs, hw + hs, hh + hs) 50 | im = im.crop(box) 51 | im = im.resize((psize, psize), Image.LANCZOS) 52 | 53 | aim = np.asarray(im) 54 | data.append(aim.flatten()) 55 | 56 | # convert from RGB to Lab 57 | daim = np.double(aim)/255.0 58 | daimlab = lab(daim) 59 | imgdata.append(daimlab.flatten()) 60 | 61 | data = np.asarray(data) 62 | imgdata = np.asarray(imgdata) 63 | griddata = np.zeros((2,ny*nx)) 64 | griddata[0,] = np.kron(range(1,ny+1),np.ones((1,nx))) 65 | griddata[1,] = np.tile(range(1,nx+1),(1,ny)) 66 | 67 | # do kernelized sorting procedure 68 | PI = KS(imgdata, griddata.T) 69 | 70 | # build and show image 71 | sorted_indices = PI.argmax(axis=1) 72 | mosaic = make_mosaic(data[sorted_indices], nx, ny) 73 | im = Image.fromarray(mosaic.astype(np.uint8)) 74 | im.save(oname) 75 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Kernelized Sorting 2 | 3 | This is a fork of code by [Novi Quadrianto](http://users.sussex.ac.uk/~nq28/kernelized_sorting.html). 4 | 5 | ![](documentation/output.jpg) 6 | 7 | List of external libraries required: 8 | 9 | - Python Imaging Library for processing images other than .png format http://www.pythonware.com/products/pil/ 10 | - Linear assignment solver hungarian 0.2 (or pyLAPJV 0.3) http://mit.edu/harold/www/code.html 11 | 12 | Running the program: 13 | - `python main_color.py` for color based image layouting 14 | - `python main_bow.py` for semantic (visual bag-of-words) image layouting **note: the required images for this example were not provided with the code** 15 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pillow 2 | hungarian -------------------------------------------------------------------------------- /utils.py: -------------------------------------------------------------------------------- 1 | import os 2 | import fnmatch 3 | import math 4 | import numpy as np 5 | 6 | def lab(Image): 7 | # Convert to CIE L*a*b* (CIELAB) 8 | WhitePoint = np.array([0.950456,1,1.088754]) 9 | Image = xyz(Image) # Convert to XYZ 10 | # Convert XYZ to CIE L*a*b* 11 | X = Image[:,:,0]/WhitePoint[0] 12 | Y = Image[:,:,1]/WhitePoint[1] 13 | Z = Image[:,:,2]/WhitePoint[2] 14 | fX = f(X) 15 | fY = f(Y) 16 | fZ = f(Z) 17 | Image[:,:,0] = 116*fY - 16 # L* 18 | Image[:,:,1] = 500*(fX - fY) # a* 19 | Image[:,:,2] = 200*(fY - fZ) # b* 20 | return Image 21 | 22 | def xyz(Image): 23 | # Convert to CIE XYZ 24 | WhitePoint = np.array([0.950456,1,1.088754]) 25 | # Undo gamma correction 26 | R = invgammacorrection(Image[:,:,0]) 27 | G = invgammacorrection(Image[:,:,1]) 28 | B = invgammacorrection(Image[:,:,2]) 29 | # Convert RGB to XYZ 30 | T = np.linalg.inv(np.array([[3.240479,-1.53715,-0.498535],[-0.969256,1.875992,0.041556],[0.055648,-0.204043,1.057311]])) 31 | Image[:,:,0] = T[0,0]*R + T[0,1]*G + T[0,2]*B # X 32 | Image[:,:,1] = T[1,0]*R + T[1,1]*G + T[1,2]*B; # Y 33 | Image[:,:,2] = T[2,0]*R + T[2,1]*G + T[2,2]*B; # Z 34 | return Image 35 | 36 | def invgammacorrection(Rp): 37 | R = np.real(((Rp + 0.099)/1.099)**(1/0.45)) 38 | i = R < 0.018 39 | R[i] = Rp[i]/4.5138 40 | return R 41 | 42 | def f(Y): 43 | fY = np.real(Y**(1.0/3)) 44 | i = (Y < 0.008856) 45 | fY[i] = Y[i]*(841.0/108) + (4.0/29) 46 | return fY 47 | 48 | # extensions can be a single tring like '.png' or '.jpg' 49 | # or a list of extensions. they should all be lowercase 50 | # but the . is important. 51 | def list_all_files(directory, extensions=None): 52 | for root, dirnames, filenames in os.walk(directory): 53 | for filename in filenames: 54 | base, ext = os.path.splitext(filename) 55 | joined = os.path.join(root, filename) 56 | if extensions is None or ( len(ext) and ext.lower() in extensions ): 57 | yield joined 58 | 59 | def find_rectangle(n, max_ratio=2): 60 | sides = [] 61 | square = int(math.sqrt(n)) 62 | for w in range(square, max_ratio * square): 63 | h = n / w 64 | used = w * h 65 | leftover = n - used 66 | sides.append((leftover, (w, h))) 67 | return sorted(sides)[0][1] 68 | 69 | def make_mosaic(images, nx, ny, channels=3): 70 | side = int(np.sqrt(len(images[0]) / channels)) 71 | images = images.reshape(-1, side, side, channels) 72 | image_gen = iter(images) 73 | mosaic = np.empty((side*ny, side*nx, channels)) 74 | for i in range(ny): 75 | ia = (i)*side 76 | ib = (i+1)*side 77 | for j in range(nx): 78 | ja = j*side 79 | jb = (j+1)*side 80 | mosaic[ia:ib, ja:jb] = next(image_gen) 81 | return mosaic -------------------------------------------------------------------------------- /vector.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2006, National ICT Australia 2 | # All rights reserved. 3 | # 4 | # The contents of this file are subject to the Mozilla Public License Version 5 | # 1.1 (the 'License'); you may not use this file except in compliance with 6 | # the License. You may obtain a copy of the License at 7 | # http://www.mozilla.org/MPL/ 8 | # 9 | # Software distributed under the License is distributed on an 'AS IS' basis, 10 | # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 11 | # for the specific language governing rights and limitations under the 12 | # License. 13 | # 14 | # Authors: Le Song (lesong@it.usyd.edu.au) and Alex Smola 15 | # (alex.smola@nicta.com.au) 16 | # Created: (20/10/2006) 17 | # Last Updated: (dd/mm/yyyy) 18 | # 19 | 20 | ##\package elefant.kernels.vector 21 | # This module contains kernel classes for vectorial data. 22 | # 23 | # The CVectorKernel class provides common interface for all kernel classes 24 | # for vectorial data. This kernel should never be instantiated as well. 25 | # All other kernel classes are derived from the CVectorKernel class. The 26 | # hierarchy for the the classes in this package is as follows: 27 | # --CKernel (abstract) 28 | # ------CVectorKernel (abstract) 29 | # ----------CDeltaKernel 30 | # ----------CLinearKernel 31 | # ----------CDotProductKernel (abstract) 32 | # --------------CPolynomialKernel 33 | # --------------CTanhKernel 34 | # --------------CExpKernel 35 | # ----------CRBFKernel (abstract) 36 | # --------------CGaussKernel 37 | # --------------CLaplaceKernel 38 | # --------------CInvDisKernel 39 | # --------------CInvSqDisKernel 40 | # --------------CBesselKernel 41 | # 42 | 43 | __version__ = '$Revision: $' 44 | # $Source$ 45 | 46 | import numpy 47 | import numpy.random as random 48 | from generic import CKernel 49 | from elefant_exceptions import CElefantConstraintException 50 | 51 | ## Generic kernel class for vectorial data 52 | # 53 | # This kernel provide common interface for all kernels operating on 54 | # vectorial data. This interface includes the following key kernel 55 | # manipulations (functions): 56 | # --Dot(x1, x2): $K(x1, x2)$ 57 | # --Expand(x1, x2, alpha): $sum_r K(x1_i,x2_r) \times alpha2_r$ 58 | # --Tensor(x1, y1, x2, y2): $K(x1_i,x2_j) \times (y1_i \times y1_j)$ 59 | # --TensorExpand(x1, y1, x2, y2, alpha2): 60 | # $sum_r K(x1_i,x2_r) \times (y1_i \times y1_r) \times alpha2_r$ 61 | # --Remember(x): Remember data x 62 | # --Forget(x): Remove remembered data x 63 | # To design a specific kernel, simply overload these methods. The generic 64 | # kernel itself should never be instantiated, although methods 65 | # Remember and Forget are implemented in this class. The Remember method 66 | # stores the inner product of an input vector. 67 | # 68 | class CVectorKernel(CKernel): 69 | def __init__( self, blocksize = 128 ): 70 | CKernel.__init__( self, blocksize ) 71 | self._name = 'Vector kernel' 72 | ## @var _cacheKernel 73 | # Cache that store the base part for the kernel matrix. 74 | # This cache facilates the incremental and decremental 75 | # computational of the kernel matrix. 76 | # 77 | self._cacheKernel = {} 78 | ## @var _typicalParam 79 | # Typical parameter for the kernel. Many kernels do not 80 | # have parameters, such linear kernel. In this case, set 81 | # zero as the typical parameter. This variable will be 82 | # usefull when optimizing the kernel matrix with respect 83 | # to the kernel matrix. 84 | # 85 | self._typicalParam = numpy.array([0]) 86 | 87 | ## Compute the kernel between two data points x1 and x2. 88 | # It returns a scale value of dot product between x1 and x2. 89 | # @param x1 [read] The first data point. 90 | # @param x2 [read] The second data point. 91 | # 92 | def K(self, x1, x2): 93 | raise NotImplementedError, \ 94 | 'CVectorKernel.K in abstract class is not implemented' 95 | 96 | ## Compute the kernel between the data points in x1 and those in x2. 97 | # It returns a matrix with entry $(ij)$ equal to $K(x1_i, x1_j)$. 98 | # If index1/index2 is 99 | # specified, only those data points in x1/x2 with indices corresponding 100 | # to index1/index2 are used to compute the kernel matrix. Furthermore, 101 | # if output is specified, the provided buffer is used explicitly to 102 | # store the kernel matrix. 103 | # @param x1 [read] The first set of data points. 104 | # @param x2 [read] The second set of data points. 105 | # @param index1 [read] The indices into the first set of data points. 106 | # @param index2 [read] The indices into the second set of data points. 107 | # @param output [write] The buffer where the output matrix is written into. 108 | # 109 | def Dot(self, x1, x2, index1=None, index2=None, output=None): 110 | raise NotImplementedError, \ 111 | 'CVectorKernel.Dot in abstract class is not implemented' 112 | 113 | ## Compute the kernel between the data points in x1 and those in x2, 114 | # then multiply the resulting kernel matrix by alpha2. 115 | # It returns a matrix with entry $(ij)$ equal to 116 | # $sum_r K(x1_i,x2_r) \times alpha2_r$. 117 | # Other parameters are defined similarly as those in Dot. 118 | # @param x1 [read] The first set of data points. 119 | # @param x2 [read] The second set of data points. 120 | # @param alpha2 [read] The set of coefficients. 121 | # @param index1 [read] The indices into the first set of data points. 122 | # @param index2 [read] The indices into the second set of data points. 123 | # @param output [write] The buffer where the output matrix is written into. 124 | # 125 | def Expand(self, x1, x2, alpha2, index1=None, index2=None): 126 | raise NotImplementedError, \ 127 | 'CVectorKernel.Expand in abstract class is not implemented' 128 | 129 | ## Compute the kernel between the data points in x1 and those in x2, 130 | # then multiply the resulting kernel matrix elementwiesely by the 131 | # the outer-product matrix between y1 and y2. It returns a matrix 132 | # with entry $(ij)$ equal to $K(x1_i,x2_j) \times (y1_i \times y1_j)$. 133 | # Other parameters are defined similarly as those in Dot. 134 | # @param x1 [read] The first set of data points. 135 | # @param y1 [read] The first set of labels. 136 | # @param x2 [read] The second set of data points. 137 | # @param y2 [read] The second set of labels. 138 | # @param index1 [read] The indices into the first set of data points. 139 | # @param index2 [read] The indices into the second set of data points. 140 | # @param output [write] The buffer where the output matrix is written into. 141 | # 142 | def Tensor(self, x1, y1, x2, y2, index1=None, index2=None): 143 | raise NotImplementedError, \ 144 | 'CVectorKernel.Tensor in abstract class is not implemented' 145 | 146 | ## Compute the kernel between the data points in x1 and those in x2, 147 | # then multiply the resulting kernel matrix elementwiesely by the 148 | # the outer-product matrix between y1 and y2, and final multiply 149 | # the resulting matrix by alpha2. It returns a matrix with entry $(ij)$ 150 | # equal to $sum_r K(x1_i,x2_r) \times (y1_i \times y1_r) \times alpha2_r$. 151 | # Other parameters are defined similarly as those in Dot. 152 | # @param x1 [read] The first set of data points. 153 | # @param y1 [read] The first set of labels. 154 | # @param x2 [read] The second set of data points. 155 | # @param y2 [read] The second set of labels. 156 | # @param index1 [read] The indices into the first set of data points. 157 | # @param index2 [read] The indices into the second set of data points. 158 | # @param output [write] The buffer where the output matrix is written into. 159 | # 160 | def TensorExpand(self, x1, y1, x2, y2, alpha2, index1=None, index2=None, \ 161 | output=None): 162 | raise NotImplementedError, \ 163 | 'CVectorKernel.K in abstract class is not implemented' 164 | 165 | ## Remember x by computing the inner product of the data points contained 166 | # in x, storing them in the cache and indexing them by the id of 167 | # x. If x have already been remembered, 168 | # the old stored information is simply overwritten. 169 | # @param x [read] The data to be remembered. 170 | # 171 | def Remember(self, x): 172 | # default behavior 173 | assert x is not None, 'x is None' 174 | assert len(x.shape) == 2, 'x is not a matrix' 175 | self._cacheData[id(x)] = (x**2).sum(axis=1) 176 | 177 | ## Remove the remembered data x. If x is not given, then all remembered 178 | # data in the cache is removed. If x has never been remembered, then 179 | # this function does nothing and return False instead. 180 | # @param x [read] The data to be removed. 181 | # 182 | def Forget(self, x=None): 183 | # default behavior 184 | if x is not None: 185 | assert len(x.shape) == 2, 'Argument 1 is has wrong shape' 186 | if self._cacheData.has_key(id(x)) is False: 187 | return False 188 | else: 189 | del self._cacheData[id(x)] 190 | else: 191 | self._cacheData.clear() 192 | 193 | return True 194 | 195 | ## Method that operates on the base part x of a kernel. 196 | # The derived classes overload this method to generate new 197 | # kernels. 198 | # @param x Base part of the kernel. 199 | # 200 | def Kappa(self, x): 201 | # default behavior 202 | return x 203 | 204 | ## Gradient of the kernel with respect to the kernel 205 | # parameter evaluated in the base part x of a kernel. 206 | # The derived classes overload this method to generate new 207 | # gradients of the kernels. 208 | # @param x Base part of the kernel. 209 | # 210 | def KappaGrad(self, x): 211 | # default behavior 212 | return numpy.zeros(x.shape) 213 | 214 | ## Function that set the parameter of the kernel. 215 | # If the derived classes have parameters, overload this 216 | # method to set the parameters. 217 | # @param param Parameters to be set. 218 | # 219 | def SetParam(self, param): 220 | # default behavior 221 | pass 222 | 223 | ## Clear the base part of the kernel computed for data x. 224 | # If x is not given, then all remembered data in the cache is removed. 225 | # If x has never been remembered, then this function does nothing 226 | # and return False instead. 227 | # @param x [read] The data whose base part is to be removed from the cache. 228 | # 229 | def ClearCacheKernel(self, x=None): 230 | # default behavior 231 | if x is not None: 232 | assert len(x.shape) == 2, "Argument 1 has wrong shape" 233 | if self._cacheKernel.has_key(id(x)) is False: 234 | return False 235 | else: 236 | del self._cacheKernel[id(x)] 237 | else: 238 | self._cacheKernel.clear() 239 | 240 | return True 241 | 242 | ## Create the cache for the base part of the kernel computed for 243 | # data x, and index them by the id of x. If x have already been 244 | # remembered, the old stored information is simply overwritten. 245 | # Overload this method to store different base part for different 246 | # kernels. 247 | # @param x [read] The data whose base part is to be cached. 248 | # 249 | def CreateCacheKernel(self, x): 250 | raise NotImplementedError, \ 251 | 'CVectorKernel.K in abstract class is not implemented' 252 | 253 | ## Dot product of x with itself with the cached base part of the kernel. 254 | # Overload this method to use the base part differently for different 255 | # kernel. If param is given, the kernel matrix is computed using 256 | # the given parameter and the current base part. Otherwise, the old 257 | # parameters are used. 258 | # @param x The data set. 259 | # @param param The new parameters. 260 | # @param output The output buffer. 261 | # 262 | def DotCacheKernel(self, x, param=None, output=None): 263 | raise NotImplementedError, \ 264 | 'CVectorKernel.K in abstract class is not implemented' 265 | 266 | ## Decrement the base part of the kernel for x1 stored in the cache 267 | # by x2. Overload this method to define the decrement of the base 268 | # part differently for different kernels. Note that this method 269 | # updates the cache for the kernel part. 270 | # @param x1 The data set whose base part has been cached. 271 | # @param x2 The data set who is to be decremented from x1. 272 | # 273 | def DecCacheKernel(self, x1, x2): 274 | raise NotImplementedError, \ 275 | 'CVectorKernel.K in abstract class is not implemented' 276 | 277 | ## Decrement the base part of the kernel for x1 stored in the cache 278 | # by x2, and return the resulting kernel matrix. If param is given, 279 | # the kernel matrix is computed using the given parameter and the 280 | # current base part. Otherwise, the old parameters are used. Overload 281 | # this method to have different behavior for different kernel. Note 282 | # that this method does NOT change the cache for the kernel part. 283 | # @param x1 The data set whose base part has been cached. 284 | # @param x2 The data set who is to be decremented from x1. 285 | # @param param The new parameters. 286 | # 287 | def DecDotCacheKernel(self, x1, x2, param=None, output=None): 288 | raise NotImplementedError, \ 289 | 'CVectorKernel.K in abstract class is not implemented' 290 | 291 | ## Gradient of the kernel matrix with respect to the kernel parameter. 292 | # If param is given, the kernel matrix is computed using the given 293 | # parameter and the current base part. Otherwise, the old parameters 294 | # are used. Overload this method to have different behavior. 295 | # @param x The data set for the kernel matrix. 296 | # @param param The kernel parameters. 297 | # 298 | def GradDotCacheKernel(self, x, param=None, output=None): 299 | # default behavior 300 | assert len(x.shape)==2, "Argument 1 has wrong shape" 301 | assert self._cacheKernel.has_key(id(x)) == True, \ 302 | "Argument 1 has not been cached" 303 | 304 | if param is not None: 305 | self.SetParam(param) 306 | 307 | n = x.shape[0] 308 | output = numpy.zeros((n,n), numpy.float64) 309 | return output 310 | 311 | #------------------------------------------------------------------------------ 312 | 313 | ## Linear kernel class 314 | # 315 | # The methods are implemente efficiently by computing the resulting 316 | # matrices block by block. 317 | # 318 | class CLinearKernel(CVectorKernel): 319 | def __init__(self, blocksize=128): 320 | CVectorKernel.__init__(self, blocksize) 321 | self._name = 'Linear kernel' 322 | 323 | ## Compute the kernel between two data points x1 and x2. 324 | # It returns a scale value of dot product between x1 and x2. 325 | # @param x1 [read] The first data point. 326 | # @param x2 [read] The second data point. 327 | # 328 | def K(self, x1, x2): 329 | assert len(x1.squeeze().shape) == 1, 'x1 is not a vector' 330 | assert len(x2.squeeze().shape) == 1, 'x2 is not a vector' 331 | return (x1.squeeze()*x2.squeeze()).sum() 332 | 333 | ## Compute the kernel between the data points in x1 and those in x2. 334 | # It returns a matrix with entry $(ij)$ equal to $K(x1_i, x1_j)$. 335 | # If index1/index2 is 336 | # specified, only those data points in x1/x2 with indices corresponding 337 | # to index1/index2 are used to compute the kernel matrix. Furthermore, 338 | # if output is specified, the provided buffer is used explicitly to 339 | # store the kernel matrix. 340 | # @param x1 [read] The first set of data points. 341 | # @param x2 [read] The second set of data points. 342 | # @param index1 [read] The indices into the first set of data points. 343 | # @param index2 [read] The indices into the second set of data points. 344 | # @param output [write] The buffer where the output matrix is written into. 345 | # 346 | def Dot(self, x1, x2, index1=None, index2=None, output=None): 347 | assert len(x1.shape) == 2, 'Argument 1 has wrong shape' 348 | assert len(x2.shape) == 2, 'Argument 2 has wrong shape' 349 | assert x1.shape[1] == x2.shape[1], \ 350 | 'Argument 1 and Argument 2 have different dimensions' 351 | 352 | if index1 is not None: 353 | x1 = x1[index1,] 354 | if index2 is not None: 355 | x2 = x2[index2,] 356 | 357 | # number of data points in x1. 358 | n1 = x1.shape[0] 359 | # number of data points in x2. 360 | n2 = x2.shape[0] 361 | # number of blocks. 362 | nb = n1 / self._blocksize 363 | 364 | if output is None: 365 | output = numpy.zeros((n1,n2), numpy.float64) 366 | 367 | # handle special cases: 368 | if index2 is not None: 369 | if len(index2) <= self._blocksize: 370 | output = numpy.dot(x1, numpy.transpose(x2)) 371 | return output 372 | 373 | # blocking 374 | lower_limit = 0 375 | upper_limit = 0 376 | for i in range(nb): 377 | upper_limit = upper_limit + self._blocksize 378 | output[lower_limit:upper_limit,] = numpy.transpose(numpy.dot(x2, numpy.transpose(x1[lower_limit:upper_limit,]))) 379 | lower_limit = upper_limit 380 | if lower_limit <= n1: 381 | output[lower_limit:n1,] = numpy.transpose(numpy.dot(x2, numpy.transpose(x1[lower_limit:n1,]))) 382 | 383 | return output 384 | 385 | ## Compute the kernel between the data points in x1 and those in x2, 386 | # then multiply the resulting kernel matrix by alpha2. 387 | # It returns a matrix with entry $(ij)$ equal to 388 | # $sum_r K(x1_i,x2_r) \times alpha2_r$. 389 | # Other parameters are defined similarly as those in Dot. 390 | # @param x1 [read] The first set of data points. 391 | # @param x2 [read] The second set of data points. 392 | # @param alpha2 [read] The set of coefficients. 393 | # @param index1 [read] The indices into the first set of data points. 394 | # @param index2 [read] The indices into the second set of data points. 395 | # @param output [write] The buffer where the output matrix is written into. 396 | # 397 | def Expand(self, x1, x2, alpha2, index1=None, index2=None, output=None): 398 | assert len(x1.shape) == 2, 'Argument 1 has wrong shape' 399 | assert len(x2.shape) == 2, 'Argument 2 has wrong shape' 400 | assert len(alpha2.shape) == 2, 'Argument 3 has wrong shape' 401 | assert x1.shape[1] == x2.shape[1], \ 402 | 'Argument 1 and 2 has different dimesions' 403 | assert x2.shape[0] == alpha2.shape[0], \ 404 | 'Argument 2 and 3 has different number of data points' 405 | 406 | if index1 is not None: 407 | x1 = x1[index1,] 408 | if index2 is not None: 409 | x2 = x2[index2,] 410 | alpha2 = alpha2[index2,] 411 | 412 | n1 = x1.shape[0] 413 | nb = n1 / self._blocksize 414 | n2 = alpha2.shape[1] 415 | 416 | if output is None: 417 | output = numpy.zeros((n1,n2), numpy.float64) 418 | 419 | # handle special cases: 420 | if index2 is not None: 421 | if len(index2) <= self._blocksize: 422 | output = numpy.dot(numpy.dot(x1, numpy.transpose(x2)), alpha2) 423 | return output 424 | 425 | # blocking 426 | lower_limit = 0 427 | upper_limit = 0 428 | for i in range(nb): 429 | upper_limit = upper_limit + self._blocksize 430 | output[lower_limit:upper_limit,] = numpy.dot(numpy.transpose(numpy.dot(x2,numpy.transpose(x1[lower_limit:upper_limit,]))), alpha2) 431 | lower_limit = upper_limit 432 | if lower_limit <= n1: 433 | output[lower_limit:n1,] = numpy.dot(numpy.transpose(numpy.dot(x2,numpy.transpose(x1[lower_limit:n1,]))), alpha2) 434 | 435 | return output 436 | 437 | ## Compute the kernel between the data points in x1 and those in x2, 438 | # then multiply the resulting kernel matrix elementwiesely by the 439 | # the outer-product matrix between y1 and y2. It returns a matrix 440 | # with entry $(ij)$ equal to $K(x1_i,x2_j) \times (y1_i \times y1_j)$. 441 | # Other parameters are defined similarly as those in Dot. 442 | # @param x1 [read] The first set of data points. 443 | # @param y1 [read] The first set of labels. 444 | # @param x2 [read] The second set of data points. 445 | # @param y2 [read] The second set of labels. 446 | # @param index1 [read] The indices into the first set of data points. 447 | # @param index2 [read] The indices into the second set of data points. 448 | # @param output [write] The buffer where the output matrix is written into. 449 | # 450 | def Tensor(self, x1, y1, x2, y2, index1=None, index2=None, output=None): 451 | assert len(x1.shape) == 2, 'Argument 1 has wrong shape' 452 | assert len(y1.shape) == 2, 'Argument 2 has wrong shape' 453 | assert x1.shape[0] == y1.shape[0], \ 454 | 'Argument 1 and 2 has different dimensions' 455 | assert len(x2.shape) == 2, 'Argument 3 has wrong shape' 456 | assert len(y2.shape) == 2, 'Argument 4 has wrong shape' 457 | assert x2.shape[0] == y2.shape[0], \ 458 | 'Argument 2 and 3 has different dimensions' 459 | 460 | if index1 is not None: 461 | x1 = x1[index1,] 462 | y1 = y1[index1,] 463 | if index2 is not None: 464 | x2 = x2[index2,] 465 | y2 = y2[index2,] 466 | 467 | n1 = x1.shape[0] 468 | nb = n1 / self._blocksize 469 | n2 = x2.shape[0] 470 | 471 | if output is None: 472 | output = numpy.zeros((n1,n2), numpy.float64) 473 | 474 | # handle special cases: 475 | if index2 is not None: 476 | if len(index2) <= self._blocksize: 477 | output = numpy.transpose(y1[:,0]*numpy.transpose(y2[:,0]*numpy.dot(x1, numpy.transpose(x2)))) 478 | return output 479 | 480 | # blocking 481 | lower_limit = 0 482 | upper_limit = 0 483 | for i in range(nb): 484 | upper_limit = upper_limit + self._blocksize 485 | output[lower_limit:upper_limit,] = y2[:,0]*numpy.transpose(y1[lower_limit:upper_limit,0]*numpy.dot(x2, numpy.transpose(x1[lower_limit:upper_limit,]))) 486 | lower_limit = upper_limit 487 | if lower_limit <= n1: 488 | output[lower_limit:n1,] = y2[:,0]*numpy.transpose(y1[lower_limit:n1,0]*numpy.dot(x2, numpy.transpose(x1[lower_limit:n1,]))) 489 | 490 | return output 491 | 492 | ## Compute the kernel between the data points in x1 and those in x2, 493 | # then multiply the resulting kernel matrix elementwiesely by the 494 | # the outer-product matrix between y1 and y2, and final multiply 495 | # the resulting matrix by alpha2. It returns a matrix with entry $(ij)$ 496 | # equal to $sum_r K(x1_i,x2_r) \times (y1_i \times y1_r) \times alpha2_r$. 497 | # Other parameters are defined similarly as those in Dot. 498 | # @param x1 [read] The first set of data points. 499 | # @param y1 [read] The first set of labels. 500 | # @param x2 [read] The second set of data points. 501 | # @param y2 [read] The second set of labels. 502 | # @param index1 [read] The indices into the first set of data points. 503 | # @param index2 [read] The indices into the second set of data points. 504 | # @param output [write] The buffer where the output matrix is written into. 505 | # 506 | def TensorExpand(self, x1, y1, x2, y2, alpha2, index1=None, index2=None, output=None): 507 | assert len(x1.shape) == 2, 'Argument 1 has wrong shape' 508 | assert len(y1.shape) == 2, 'Argument 2 has wrong shape' 509 | assert x1.shape[0] == y1.shape[0], \ 510 | 'Argument 1 and 2 have different dimensions' 511 | assert len(x2.shape) == 2, 'Argument 3 has wrong shape' 512 | assert len(y2.shape) == 2, 'Argument 4 has wrong shape' 513 | assert x2.shape[0] == y2.shape[0], \ 514 | 'Argument 3 and 4 have different dimensions' 515 | assert len(alpha2.shape) == 2, 'Argument 5 has wrong shape' 516 | assert x2.shape[0] == alpha2.shape[0], \ 517 | 'Argument 3 and 5 have different number of data points' 518 | 519 | if index1 is not None: 520 | x1 = x1[index1,] 521 | y1 = y1[index1,] 522 | if index2 is not None: 523 | x2 = x2[index2,] 524 | y2 = y2[index2,] 525 | alpha2 = alpha2[index2,] 526 | 527 | n1 = x1.shape[0] 528 | nb = n1 / self._blocksize 529 | n2 = alpha2.shape[1] 530 | 531 | if output is None: 532 | output = numpy.zeros((n1,n2), numpy.float64) 533 | 534 | # handle special cases: 535 | if index2 is not None: 536 | if len(index2) <= self._blocksize: 537 | output = numpy.transpose(y1[:,0] * numpy.transpose(numpy.dot(y2[:,0]*numpy.dot(x1,numpy.transpose(x2)), alpha2))) 538 | return output 539 | 540 | # blocking 541 | lower_limit = 0 542 | upper_limit = 0 543 | for i in range(nb): 544 | upper_limit = upper_limit + self._blocksize 545 | output[lower_limit:upper_limit,] = numpy.dot(y2[:,0]*numpy.transpose(y1[lower_limit:upper_limit,0] * numpy.dot(x2,numpy.transpose(x1[lower_limit:upper_limit,]))), alpha2) 546 | lower_limit = upper_limit 547 | if lower_limit <= n1: 548 | output[lower_limit:n1,] = numpy.dot(y2[:,0]*numpy.transpose(y1[lower_limit:n1,0] * numpy.dot(x2,numpy.transpose(x1[lower_limit:n1,]))), alpha2) 549 | 550 | return output 551 | 552 | ## Create the cache for the base part of the kernel computed for 553 | # data x, and index them by the id of x. If x have already been 554 | # remembered, the old stored information is simply overwritten. 555 | # @param x [read] The data whose base part is to be cached. 556 | # 557 | def CreateCacheKernel(self, x): 558 | assert len(x.shape) == 2, 'Argument 1 has wrong shape' 559 | n = x.shape[0] 560 | nb = n / self._blocksize 561 | 562 | # create the cache space 563 | if self._cacheKernel.has_key(id(x)): 564 | self.ClearCacheKernel(x) 565 | tmpCacheKernel = numpy.zeros((n,n), numpy.float64) 566 | self._cacheKernel[id(x)] = tmpCacheKernel 567 | 568 | # blocking 569 | lower_limit = 0 570 | upper_limit = 0 571 | for i in range(nb): 572 | upper_limit = upper_limit + self._blocksize 573 | tmpCacheKernel[lower_limit:upper_limit,] = numpy.transpose(numpy.dot(x, numpy.transpose(x[lower_limit:upper_limit,]))) 574 | lower_limit = upper_limit 575 | if lower_limit <= n: 576 | tmpCacheKernel[lower_limit:n,] = numpy.transpose(numpy.dot(x, numpy.transpose(x[lower_limit:n,]))) 577 | 578 | return True 579 | 580 | ## Dot product of x with itself with the cached base part of the kernel. 581 | # If param is given, the kernel matrix is computed using 582 | # the given parameter and the current base part. Otherwise, the old 583 | # parameters are used. 584 | # @param x The data set. 585 | # @param param The new parameters. 586 | # @param output The output buffer. 587 | # 588 | def DotCacheKernel(self, x, param=None, output=None): 589 | assert len(x.shape)==2, 'Argument 1 has wrong shape' 590 | assert self._cacheKernel.has_key(id(x)) == True, \ 591 | 'Argument 1 has not been cached' 592 | 593 | n = x.shape[0] 594 | nb = n / self._blocksize 595 | tmpCacheKernel = self._cacheKernel[id(x)] 596 | 597 | # set parameters. 598 | if param is not None: 599 | self.SetParam(param) 600 | 601 | if output is None: 602 | output = numpy.zeros((n,n), numpy.float64) 603 | 604 | # blocking 605 | lower_limit = 0 606 | upper_limit = 0 607 | for i in range(nb): 608 | upper_limit = upper_limit + self._blocksize 609 | output[lower_limit:upper_limit,] = tmpCacheKernel[lower_limit:upper_limit,] 610 | lower_limit = upper_limit 611 | if lower_limit <= n: 612 | output[lower_limit:n,] = tmpCacheKernel[lower_limit:n,] 613 | 614 | return output 615 | 616 | ## Decrement the base part of the kernel for x1 stored in the cache 617 | # by x2. Note that this method updates the cache for the kernel part. 618 | # @param x1 The data set whose base part has been cached. 619 | # @param x2 The data set who is to be decremented from x1. 620 | # 621 | def DecCacheKernel(self, x1, x2): 622 | assert len(x1.shape) == 2, 'Argument 1 has wrong shape' 623 | assert len(x2.shape) == 2, 'Argument 2 has wrong shape' 624 | assert x1.shape[0] == x2.shape[0], \ 625 | 'Argument 1 and 2 have different number of data points' 626 | assert self._cacheKernel.has_key(id(x1)) == True, \ 627 | 'Argument 1 has not been cached' 628 | 629 | n = x1.shape[0] 630 | nb = n / self._blocksize 631 | tmpCacheKernel = self._cacheKernel[id(x1)] 632 | 633 | # blocking 634 | lower_limit = 0 635 | upper_limit = 0 636 | for i in range(nb): 637 | upper_limit = upper_limit + self._blocksize 638 | tmpCacheKernel[lower_limit:upper_limit,] = tmpCacheKernel[lower_limit:upper_limit,] \ 639 | - numpy.transpose(numpy.dot(x2, numpy.transpose(x2[lower_limit:upper_limit,]))) 640 | lower_limit = upper_limit 641 | if lower_limit <= n: 642 | tmpCacheKernel[lower_limit:n,] = tmpCacheKernel[lower_limit:n,] \ 643 | - numpy.transpose(numpy.dot(x2, numpy.transpose(x2[lower_limit:n,]))) 644 | 645 | return True 646 | 647 | ## Decrement the base part of the kernel for x1 stored in the cache 648 | # by x2, and return the resulting kernel matrix. If param is given, 649 | # the kernel matrix is computed using the given parameter and the 650 | # current base part. Otherwise, the old parameters are used. Note 651 | # that this method does NOT change the cache for the kernel part. 652 | # @param x1 The data set whose base part has been cached. 653 | # @param x2 The data set who is to be decremented from x1. 654 | # @param param The new parameters. 655 | # 656 | def DecDotCacheKernel(self, x1, x2, param=None, output=None): 657 | assert len(x1.shape) == 2, 'Argument 1 has wrong shape' 658 | assert len(x2.shape) == 2, 'Argument 2 has wrong shape' 659 | assert x1.shape[0] == x2.shape[0], \ 660 | 'Argument 1 and 2 have different number of data points' 661 | assert self._cacheKernel.has_key(id(x1)) == True, \ 662 | 'Argument 1 has not been cached' 663 | 664 | n = x1.shape[0] 665 | nb = n / self._blocksize 666 | tmpCacheKernel = self._cacheKernel[id(x1)] 667 | 668 | # set parameters. 669 | if param is not None: 670 | self.SetParam(param) 671 | 672 | if output is None: 673 | output = numpy.zeros((n,n), numpy.float64) 674 | 675 | # blocking 676 | lower_limit = 0 677 | upper_limit = 0 678 | for i in range(nb): 679 | upper_limit = upper_limit + self._blocksize 680 | output[lower_limit:upper_limit,] = tmpCacheKernel[lower_limit:upper_limit,] \ 681 | - numpy.transpose(numpy.dot(x2, numpy.transpose(x2[lower_limit:upper_limit,]))) 682 | lower_limit = upper_limit 683 | if lower_limit <= n: 684 | output[lower_limit:n,] = tmpCacheKernel[lower_limit:n,] \ 685 | - numpy.transpose(numpy.dot(x2, numpy.transpose(x2[lower_limit:n,]))) 686 | 687 | return output 688 | 689 | #------------------------------------------------------------------------------ 690 | 691 | ## Dot Product kernel class 692 | # 693 | # All kernels that are function of the dot product between the two 694 | # data points, ie. $K(x1,x2)=Kappa(x1^\top x2). 695 | # The methods are implemente efficiently by computing the resulting 696 | # matrices block by block. All kernel classes derived from CDotProductKernel 697 | # differ only in their choice of Kappa function. 698 | # 699 | class CDotProductKernel(CVectorKernel): 700 | def __init__(self, blocksize=128): 701 | CVectorKernel.__init__(self, blocksize) 702 | self._name = 'Dot Product kernel' 703 | 704 | ## Compute the kernel between two data points x1 and x2. 705 | # It returns a scale value of dot product between x1 and x2. 706 | # @param x1 [read] The first data point. 707 | # @param x2 [read] The second data point. 708 | # 709 | def K(self, x1, x2): 710 | assert len(x1.squeeze().shape) == 1, 'x1 is not a vector' 711 | assert len(x2.squeeze().shape) == 1, 'x2 is not a vector' 712 | return (x1.squeeze()*x2.squeeze()).sum() 713 | 714 | ## Compute the kernel between the data points in x1 and those in x2. 715 | # It returns a matrix with entry $(ij)$ equal to $K(x1_i, x1_j)$. 716 | # If index1/index2 is 717 | # specified, only those data points in x1/x2 with indices corresponding 718 | # to index1/index2 are used to compute the kernel matrix. Furthermore, 719 | # if output is specified, the provided buffer is used explicitly to 720 | # store the kernel matrix. 721 | # @param x1 [read] The first set of data points. 722 | # @param x2 [read] The second set of data points. 723 | # @param index1 [read] The indices into the first set of data points. 724 | # @param index2 [read] The indices into the second set of data points. 725 | # @param output [write] The buffer where the output matrix is written into. 726 | # 727 | def Dot(self, x1, x2, index1=None, index2=None, output=None): 728 | assert len(x1.shape) == 2, 'Argument 1 has wrong shape' 729 | assert len(x2.shape) == 2, 'Argument 2 has wrong shape' 730 | assert x1.shape[1] == x2.shape[1], \ 731 | 'Argument 1 and Argument 2 have different dimensions' 732 | 733 | if index1 is not None: 734 | x1 = x1[index1,] 735 | if index2 is not None: 736 | x2 = x2[index2,] 737 | 738 | # number of data points in x1. 739 | n1 = x1.shape[0] 740 | # number of data points in x2. 741 | n2 = x2.shape[0] 742 | # number of blocks. 743 | nb = n1 / self._blocksize 744 | 745 | if output is None: 746 | output = numpy.zeros((n1,n2), numpy.float64) 747 | 748 | # handle special cases: 749 | if index2 is not None: 750 | if len(index2) <= self._blocksize: 751 | output = self.Kappa(numpy.dot(x1, numpy.transpose(x2))) 752 | return output 753 | 754 | # blocking 755 | lower_limit = 0 756 | upper_limit = 0 757 | for i in range(nb): 758 | upper_limit = upper_limit + self._blocksize 759 | output[lower_limit:upper_limit,] = self.Kappa(numpy.transpose(numpy.dot(x2, numpy.transpose(x1[lower_limit:upper_limit,])))) 760 | lower_limit = upper_limit 761 | if lower_limit <= n1: 762 | output[lower_limit:n1,] = self.Kappa(numpy.transpose(numpy.dot(x2, numpy.transpose(x1[lower_limit:n1,])))) 763 | 764 | return output 765 | 766 | ## Compute the kernel between the data points in x1 and those in x2, 767 | # then multiply the resulting kernel matrix by alpha2. 768 | # It returns a matrix with entry $(ij)$ equal to 769 | # $sum_r K(x1_i,x2_r) \times alpha2_r$. 770 | # Other parameters are defined similarly as those in Dot. 771 | # @param x1 [read] The first set of data points. 772 | # @param x2 [read] The second set of data points. 773 | # @param alpha2 [read] The set of coefficients. 774 | # @param index1 [read] The indices into the first set of data points. 775 | # @param index2 [read] The indices into the second set of data points. 776 | # @param output [write] The buffer where the output matrix is written into. 777 | # 778 | def Expand(self, x1, x2, alpha2, index1=None, index2=None, output=None): 779 | assert len(x1.shape) == 2, 'Argument 1 has wrong shape' 780 | assert len(x2.shape) == 2, 'Argument 2 has wrong shape' 781 | assert len(alpha2.shape) == 2, 'Argument 3 has wrong shape' 782 | assert x1.shape[1] == x2.shape[1], \ 783 | 'Argument 1 and 2 has different dimesions' 784 | assert x2.shape[0] == alpha2.shape[0], \ 785 | 'Argument 2 and 3 has different number of data points' 786 | 787 | if index1 is not None: 788 | x1 = x1[index1,] 789 | if index2 is not None: 790 | x2 = x2[index2,] 791 | alpha2 = alpha2[index2,] 792 | 793 | n1 = x1.shape[0] 794 | nb = n1 / self._blocksize 795 | n2 = alpha2.shape[1] 796 | 797 | if output is not None: 798 | output = output 799 | else: 800 | output = numpy.zeros((n1,n2), numpy.float64) 801 | 802 | # handle special cases: 803 | if index2 is not None: 804 | if len(index2) <= self._blocksize: 805 | output = numpy.dot(self.Kappa(numpy.dot(x1, numpy.transpose(x2))), alpha2) 806 | return output 807 | 808 | # blocking 809 | lower_limit = 0 810 | upper_limit = 0 811 | for i in range(nb): 812 | upper_limit = upper_limit + self._blocksize 813 | output[lower_limit:upper_limit,] = numpy.dot(self.Kappa(numpy.transpose(numpy.dot(x2,numpy.transpose(x1[lower_limit:upper_limit,])))), alpha2) 814 | lower_limit = upper_limit 815 | if lower_limit <= n1: 816 | output[lower_limit:n1,] = numpy.dot(self.Kappa(numpy.transpose(numpy.dot(x2,numpy.transpose(x1[lower_limit:n1,])))), alpha2) 817 | 818 | return output 819 | 820 | ## Compute the kernel between the data points in x1 and those in x2, 821 | # then multiply the resulting kernel matrix elementwiesely by the 822 | # the outer-product matrix between y1 and y2. It returns a matrix 823 | # with entry $(ij)$ equal to $K(x1_i,x2_j) \times (y1_i \times y1_j)$. 824 | # Other parameters are defined similarly as those in Dot. 825 | # @param x1 [read] The first set of data points. 826 | # @param y1 [read] The first set of labels. 827 | # @param x2 [read] The second set of data points. 828 | # @param y2 [read] The second set of labels. 829 | # @param index1 [read] The indices into the first set of data points. 830 | # @param index2 [read] The indices into the second set of data points. 831 | # @param output [write] The buffer where the output matrix is written into. 832 | # 833 | def Tensor(self, x1, y1, x2, y2, index1=None, index2=None, output=None): 834 | assert len(x1.shape) == 2, 'Argument 1 has wrong shape' 835 | assert len(y1.shape) == 2, 'Argument 2 has wrong shape' 836 | assert x1.shape[0] == y1.shape[0], \ 837 | 'Argument 1 and 2 has different dimensions' 838 | assert len(x2.shape) == 2, 'Argument 3 has wrong shape' 839 | assert len(y2.shape) == 2, 'Argument 4 has wrong shape' 840 | assert x2.shape[0] == y2.shape[0], \ 841 | 'Argument 2 and 3 has different dimensions' 842 | 843 | if index1 is not None: 844 | x1 = x1[index1,] 845 | y1 = y1[index1,] 846 | if index2 is not None: 847 | x2 = x2[index2,] 848 | y2 = y2[index2,] 849 | 850 | n1 = x1.shape[0] 851 | nb = n1 / self._blocksize 852 | n2 = x2.shape[0] 853 | 854 | if output is None: 855 | output = numpy.zeros((n1,n2), numpy.float64) 856 | 857 | # handle special cases: 858 | if index2 is not None: 859 | if len(index2) <= self._blocksize: 860 | output = numpy.transpose(y1[:,0]*numpy.transpose(y2[:,0]*self.Kappa(numpy.dot(x1, numpy.transpose(x2))))) 861 | return output 862 | 863 | # blocking 864 | lower_limit = 0 865 | upper_limit = 0 866 | for i in range(nb): 867 | upper_limit = upper_limit + self._blocksize 868 | output[lower_limit:upper_limit,] = y2[:,0]*numpy.transpose(y1[lower_limit:upper_limit,0]*self.Kappa(numpy.dot(x2, numpy.transpose(x1[lower_limit:upper_limit,])))) 869 | lower_limit = upper_limit 870 | if lower_limit <= n1: 871 | output[lower_limit:n1,] = y2[:,0]*numpy.transpose(y1[lower_limit:n1,0]*self.Kappa(numpy.dot(x2, numpy.transpose(x1[lower_limit:n1,])))) 872 | 873 | return output 874 | 875 | ## Compute the kernel between the data points in x1 and those in x2, 876 | # then multiply the resulting kernel matrix elementwiesely by the 877 | # the outer-product matrix between y1 and y2, and final multiply 878 | # the resulting matrix by alpha2. It returns a matrix with entry $(ij)$ 879 | # equal to $sum_r K(x1_i,x2_r) \times (y1_i \times y1_r) \times alpha2_r$. 880 | # Other parameters are defined similarly as those in Dot. 881 | # @param x1 [read] The first set of data points. 882 | # @param y1 [read] The first set of labels. 883 | # @param x2 [read] The second set of data points. 884 | # @param y2 [read] The second set of labels. 885 | # @param index1 [read] The indices into the first set of data points. 886 | # @param index2 [read] The indices into the second set of data points. 887 | # @param output [write] The buffer where the output matrix is written into. 888 | # 889 | def TensorExpand(self, x1, y1, x2, y2, alpha2, index1=None, index2=None, output=None): 890 | assert len(x1.shape) == 2, 'Argument 1 has wrong shape' 891 | assert len(y1.shape) == 2, 'Argument 2 has wrong shape' 892 | assert x1.shape[0] == y1.shape[0], \ 893 | 'Argument 1 and 2 have different dimensions' 894 | assert len(x2.shape) == 2, 'Argument 3 has wrong shape' 895 | assert len(y2.shape) == 2, 'Argument 4 has wrong shape' 896 | assert x2.shape[0] == y2.shape[0], \ 897 | 'Argument 3 and 4 have different dimensions' 898 | assert len(alpha2.shape) == 2, 'Argument 5 has wrong shape' 899 | assert x2.shape[0] == alpha2.shape[0], \ 900 | 'Argument 3 and 5 have different number of data points' 901 | 902 | if index1 is not None: 903 | x1 = x1[index1,] 904 | y1 = y1[index1,] 905 | if index2 is not None: 906 | x2 = x2[index2,] 907 | y2 = y2[index2,] 908 | alpha2 = alpha2[index2,] 909 | 910 | n1 = x1.shape[0] 911 | nb = n1 / self._blocksize 912 | n2 = alpha2.shape[1] 913 | 914 | if output is None: 915 | output = numpy.zeros((n1,n2), numpy.float64) 916 | 917 | # handle special cases: 918 | if index2 is not None: 919 | if len(index2) <= self._blocksize: 920 | output = numpy.transpose(y1[:,0] * numpy.transpose(numpy.dot(y2[:,0]*self.Kappa(numpy.dot(x1,numpy.transpose(x2))), alpha2))) 921 | return output 922 | 923 | # blocking 924 | lower_limit = 0 925 | upper_limit = 0 926 | for i in range(nb): 927 | upper_limit = upper_limit + self._blocksize 928 | output[lower_limit:upper_limit,] = numpy.dot(y2[:,0]*numpy.transpose(y1[lower_limit:upper_limit,0] * self.Kappa(numpy.dot(x2,numpy.transpose(x1[lower_limit:upper_limit,])))), alpha2) 929 | lower_limit = upper_limit 930 | if lower_limit <= n1: 931 | output[lower_limit:n1,] = numpy.dot(y2[:,0]*numpy.transpose(y1[lower_limit:n1,0] * self.Kappa(numpy.dot(x2,numpy.transpose(x1[lower_limit:n1,])))), alpha2) 932 | 933 | return output 934 | 935 | ## Create the cache for the base part of the kernel computed for 936 | # data x, and index them by the id of x. If x have already been 937 | # remembered, the old stored information is simply overwritten. 938 | # @param x [read] The data whose base part is to be cached. 939 | # 940 | def CreateCacheKernel(self, x): 941 | assert len(x.shape) == 2, 'Argument 1 has wrong shape' 942 | n = x.shape[0] 943 | nb = n / self._blocksize 944 | 945 | # create the cache space 946 | if self._cacheKernel.has_key(id(x)): 947 | self.ClearCacheKernel(x) 948 | tmpCacheKernel = numpy.zeros((n,n), numpy.float64) 949 | self._cacheKernel[id(x)] = tmpCacheKernel 950 | 951 | # blocking 952 | lower_limit = 0 953 | upper_limit = 0 954 | for i in range(nb): 955 | upper_limit = upper_limit + self._blocksize 956 | tmpCacheKernel[lower_limit:upper_limit,] = numpy.transpose(numpy.dot(x, numpy.transpose(x[lower_limit:upper_limit,]))) 957 | lower_limit = upper_limit 958 | if lower_limit <= n: 959 | tmpCacheKernel[lower_limit:n,] = numpy.transpose(numpy.dot(x, numpy.transpose(x[lower_limit:n,]))) 960 | 961 | return True 962 | 963 | ## Dot product of x with itself with the cached base part of the kernel. 964 | # If param is given, the kernel matrix is computed using 965 | # the given parameter and the current base part. Otherwise, the old 966 | # parameters are used. 967 | # @param x The data set. 968 | # @param param The new parameters. 969 | # @param output The output buffer. 970 | # 971 | def DotCacheKernel(self, x, param=None, output=None): 972 | assert len(x.shape)==2, 'Argument 1 has wrong shape' 973 | assert self._cacheKernel.has_key(id(x)) == True, \ 974 | 'Argument 1 has not been cached' 975 | 976 | n = x.shape[0] 977 | nb = n / self._blocksize 978 | tmpCacheKernel = self._cacheKernel[id(x)] 979 | 980 | # set parameters. 981 | if param is not None: 982 | self.SetParam(param) 983 | 984 | if output is None: 985 | output = numpy.zeros((n,n), numpy.float64) 986 | 987 | # blocking 988 | lower_limit = 0 989 | upper_limit = 0 990 | for i in range(nb): 991 | upper_limit = upper_limit + self._blocksize 992 | output[lower_limit:upper_limit,] = self.Kappa(tmpCacheKernel[lower_limit:upper_limit,]) 993 | lower_limit = upper_limit 994 | if lower_limit <= n: 995 | output[lower_limit:n,] = self.Kappa(tmpCacheKernel[lower_limit:n,]) 996 | 997 | return output 998 | 999 | ## Decrement the base part of the kernel for x1 stored in the cache 1000 | # by x2. Note that this method updates the cache for the kernel part. 1001 | # @param x1 The data set whose base part has been cached. 1002 | # @param x2 The data set who is to be decremented from x1. 1003 | # 1004 | def DecCacheKernel(self, x1, x2): 1005 | assert len(x1.shape) == 2, 'Argument 1 has wrong shape' 1006 | assert len(x2.shape) == 2, 'Argument 2 has wrong shape' 1007 | assert x1.shape[0] == x2.shape[0], \ 1008 | 'Argument 1 and 2 have different number of data points' 1009 | assert self._cacheKernel.has_key(id(x1)) == True, \ 1010 | 'Argument 1 has not been cached' 1011 | 1012 | n = x1.shape[0] 1013 | nb = n / self._blocksize 1014 | tmpCacheKernel = self._cacheKernel[id(x1)] 1015 | 1016 | # blocking 1017 | lower_limit = 0 1018 | upper_limit = 0 1019 | for i in range(nb): 1020 | upper_limit = upper_limit + self._blocksize 1021 | tmpCacheKernel[lower_limit:upper_limit,] = tmpCacheKernel[lower_limit:upper_limit,] \ 1022 | - numpy.transpose(numpy.dot(x2, numpy.transpose(x2[lower_limit:upper_limit,]))) 1023 | lower_limit = upper_limit 1024 | if lower_limit <= n: 1025 | tmpCacheKernel[lower_limit:n,] = tmpCacheKernel[lower_limit:n,] \ 1026 | - numpy.transpose(numpy.dot(x2, numpy.transpose(x2[lower_limit:n,]))) 1027 | 1028 | return True 1029 | 1030 | ## Decrement the base part of the kernel for x1 stored in the cache 1031 | # by x2, and return the resulting kernel matrix. If param is given, 1032 | # the kernel matrix is computed using the given parameter and the 1033 | # current base part. Otherwise, the old parameters are used. Note 1034 | # that this method does NOT change the cache for the kernel part. 1035 | # @param x1 The data set whose base part has been cached. 1036 | # @param x2 The data set who is to be decremented from x1. 1037 | # @param param The new parameters. 1038 | # 1039 | def DecDotCacheKernel(self, x1, x2, param=None, output=None): 1040 | assert len(x1.shape) == 2, 'Argument 1 has wrong shape' 1041 | assert len(x2.shape) == 2, 'Argument 2 has wrong shape' 1042 | assert x1.shape[0] == x2.shape[0], \ 1043 | 'Argument 1 and 2 have different number of data points' 1044 | assert self._cacheKernel.has_key(id(x1)) == True, \ 1045 | 'Argument 1 has not been cached' 1046 | 1047 | n = x1.shape[0] 1048 | nb = n / self._blocksize 1049 | tmpCacheKernel = self._cacheKernel[id(x1)] 1050 | 1051 | # set parameters. 1052 | if param is not None: 1053 | self.SetParam(param) 1054 | 1055 | if output is None: 1056 | output = numpy.zeros((n,n), numpy.float64) 1057 | 1058 | # blocking 1059 | lower_limit = 0 1060 | upper_limit = 0 1061 | for i in range(nb): 1062 | upper_limit = upper_limit + self._blocksize 1063 | output[lower_limit:upper_limit,] = numpy.transpose(numpy.dot(x2, numpy.transpose(x2[lower_limit:upper_limit,]))) 1064 | output[lower_limit:upper_limit,] = self.Kappa(tmpCacheKernel[lower_limit:upper_limit,] \ 1065 | - output[lower_limit:upper_limit,]) 1066 | lower_limit = upper_limit 1067 | if lower_limit <= n: 1068 | output[lower_limit:n,] = numpy.transpose(numpy.dot(x2, numpy.transpose(x2[lower_limit:n,]))) 1069 | output[lower_limit:n,] = self.Kappa(tmpCacheKernel[lower_limit:n,] \ 1070 | - output[lower_limit:n,]) 1071 | 1072 | return output 1073 | 1074 | ## Gradient of the kernel matrix with respect to the kernel parameter. 1075 | # If param is given, the kernel matrix is computed using the given 1076 | # parameter and the current base part. Otherwise, the old parameters 1077 | # are used. 1078 | # @param x The data set for the kernel matrix. 1079 | # @param param The kernel parameters. 1080 | # 1081 | def GradDotCacheKernel(self, x, param=None, output=None): 1082 | assert len(x.shape) == 2, "Argument 1 has wrong shape" 1083 | assert self._cacheKernel.has_key(id(x)) == True, \ 1084 | "Argument 1 has not been cached" 1085 | 1086 | n = x.shape[0] 1087 | nb = n / self._blocksize 1088 | tmpCacheKernel = self._cacheKernel[id(x)] 1089 | 1090 | if param is not None: 1091 | self.SetParam(param) 1092 | 1093 | if output is None: 1094 | output = numpy.zeros((n,n), numpy.float64) 1095 | 1096 | # blocking 1097 | lower_limit = 0 1098 | upper_limit = 0 1099 | for i in range(nb): 1100 | upper_limit = upper_limit + self._blocksize 1101 | output[lower_limit:upper_limit,] = self.KappaGrad(tmpCacheKernel[lower_limit:upper_limit,]) 1102 | lower_limit = upper_limit 1103 | if lower_limit <= n: 1104 | output[lower_limit:n,] = self.KappaGrad(tmpCacheKernel[lower_limit:n,]) 1105 | 1106 | return output 1107 | 1108 | ## Polynomial kernel 1109 | # 1110 | # Kernel of the form: $K(x1,x2)=(scale (x1^\top x2) + offset)^degree$. 1111 | # This is implemented by the Kappa function. 1112 | # 1113 | class CPolynomialKernel(CDotProductKernel): 1114 | def __init__(self, degree=2, offset=1.0, scale=1.0, blocksize=128): 1115 | CDotProductKernel.__init__(self, blocksize) 1116 | self._name = 'Polynomial kernel' 1117 | self._scale = scale 1118 | self._offset = offset 1119 | self._degree = degree 1120 | 1121 | ## Method that operates on the base part of the kernel to 1122 | # generate the new kernel 1123 | # @param x Base part of the kernel matrix. 1124 | # 1125 | def Kappa(self, x): 1126 | return (self._scale * x + self._offset) ** self._degree 1127 | 1128 | ## Tanh kernel 1129 | # 1130 | # Kernel of the form : $K(x1,x2)=\tanh(scale (x1^\top x2) + offset)$. 1131 | # This is implemented by the Kappa function. 1132 | # 1133 | class CTanhKernel(CDotProductKernel): 1134 | def __init__(self, offset=1.0, scale=1.0, blocksize=128): 1135 | CDotProductKernel.__init__(self, blocksize) 1136 | self._name = 'Tahn kernel' 1137 | self._scale = scale 1138 | self._offset = offset 1139 | 1140 | ## Method that operates on the base part of the kernel to 1141 | # generate the new kernel 1142 | # @param x Base part of the kernel matrix. 1143 | # 1144 | def Kappa(self, x): 1145 | return numpy.tanh(self._scale * x + self._offset) 1146 | 1147 | ## Exponential kernel 1148 | # 1149 | # Kernel of the form: $K(x1,x2)=\exp(scale (x1^\top x2) + offset) 1150 | # This is implemented by the Kappa function. 1151 | # 1152 | class CExpKernel(CDotProductKernel): 1153 | def __init__(self, offset=0, scale=1.0, blocksize=128): 1154 | CDotProductKernel.__init__(self, blocksize) 1155 | self._name = 'Expential kernel' 1156 | self._scale = scale 1157 | self._offset = offset 1158 | 1159 | ## Method that operates on the base part of the kernel to 1160 | # generate the new kernel 1161 | # @param x Base part of the kernel matrix. 1162 | # 1163 | def Kappa(self, x): 1164 | return numpy.exp(self._scale * x + self._offset) 1165 | 1166 | #------------------------------------------------------------------------------ 1167 | 1168 | ## RBF kernels. 1169 | # 1170 | # Distance-based kernel, where Gauss, Laplace and Bessel kernels are derived. 1171 | # This class of kernels has the form: $K(x1,x2)=f(\|x1-x2\|)$ 1172 | # The methods are implemente efficiently by computing the resulting 1173 | # matrices block by block. All kernel classes derived from CRBFKernel 1174 | # differ only in their choice of Kappa function. 1175 | # 1176 | class CRBFKernel(CVectorKernel): 1177 | def __init__(self, blocksize=128): 1178 | CVectorKernel.__init__(self, blocksize=blocksize) 1179 | self._name = 'RBF kernel' 1180 | 1181 | ## Method that operates on the base part of a kernel. 1182 | # The derived classes overload this method to generate new 1183 | # kernels. 1184 | # @param x Base part of the kernel matrix. 1185 | # 1186 | def Kappa(self, x): 1187 | return x 1188 | 1189 | ## Compute the kernel between two data points x1 and x2. 1190 | # It returns a scale value of dot product between x1 and x2. 1191 | # @param x1 [read] The first data point. 1192 | # @param x2 [read] The second data point. 1193 | # 1194 | def K(self, x1, x2): 1195 | ##assert len(x1.squeeze().shape) == 1, 'x1 is not a vector' 1196 | ##assert len(x2.squeeze().shape) == 1, 'x2 is not a vector' 1197 | 1198 | v = (x1 - x2).squeeze() 1199 | return self.Kappa(numpy.sum(v*v)) 1200 | 1201 | ## Compute the square distance using inner products. It computes 1202 | # the distance by following formular: 1203 | # $(x1-x2)^2 = x1^2 - 2 x1 x2 + x2^2$ 1204 | # @param dest [write] The destination where the results are stored. 1205 | # @param x1_x2 [read] The inner product matrix between x1 and x2. 1206 | # @param dot_x1 [read] The inner product of the data in x1. 1207 | # @param dot_x2 [read] The inner product of the data in x2. 1208 | # 1209 | def KappaSqDis(self, dest, x1_x2, dot_x1, dot_x2): 1210 | dest[:,] = self.Kappa(- 2.0 * x1_x2 + numpy.add.outer(dot_x1, dot_x2)) 1211 | 1212 | ## Compute the kernel between the data points in x1 and those in x2. 1213 | # It returns a matrix with entry $(ij)$ equal to $K(x1_i, x1_j)$. 1214 | # If index1/index2 is 1215 | # specified, only those data points in x1/x2 with indices corresponding 1216 | # to index1/index2 are used to compute the kernel matrix. Furthermore, 1217 | # if output is specified, the provided buffer is used explicitly to 1218 | # store the kernel matrix. 1219 | # @param x1 [read] The first set of data points. 1220 | # @param x2 [read] The second set of data points. 1221 | # @param index1 [read] The indices into the first set of data points. 1222 | # @param index2 [read] The indices into the second set of data points. 1223 | # @param output [write] The buffer where the output matrix is written into. 1224 | # 1225 | def Dot(self, x1, x2, index1=None, index2=None, output=None): 1226 | assert len(x1.shape) == 2, 'Argument 1 has wrong shape' 1227 | assert len(x2.shape) == 2, 'Argument 2 has wrong shape' 1228 | assert x1.shape[1] == x2.shape[1], \ 1229 | 'Argument 1 and Argument 2 have different dimensions' 1230 | 1231 | # retrieve remembered data from the cache. 1232 | flg1 = False 1233 | if self._cacheData.has_key(id(x1)): 1234 | dot_x1 = self._cacheData[id(x1)] 1235 | flg1 = True 1236 | flg2 = False 1237 | if self._cacheData.has_key(id(x2)): 1238 | dot_x2 = self._cacheData[id(x2)] 1239 | flg2 = True 1240 | 1241 | if index1 is not None: 1242 | x1 = x1[index1,] 1243 | if flg1 is True: 1244 | dot_x1 = dot_x1[index1,] 1245 | else: 1246 | dot_x1 = numpy.sum(x1**2, 1) 1247 | else: 1248 | if flg1 is False: 1249 | dot_x1 = numpy.sum(x1**2, 1) 1250 | 1251 | if index2 is not None: 1252 | x2 = x2[index2,] 1253 | if flg2 is True: 1254 | dot_x2 = dot_x2[index2,] 1255 | else: 1256 | dot_x2 = numpy.sum(x2**2, 1) 1257 | else: 1258 | if flg2 is False: 1259 | dot_x2 = numpy.sum(x2**2, 1) 1260 | 1261 | # number of data points in x1. 1262 | n1 = x1.shape[0] 1263 | # number of data points in x2. 1264 | n2 = x2.shape[0] 1265 | # number of blocks. 1266 | nb = n1 / self._blocksize 1267 | 1268 | if output is None: 1269 | output = numpy.zeros((n1,n2), numpy.float64) 1270 | 1271 | # handle special cases: 1272 | if index2 is not None: 1273 | if len(index2) <= self._blocksize: 1274 | output = numpy.dot(x1, numpy.transpose(x2)) 1275 | self.KappaSqDis(output, output, dot_x1, dot_x2) 1276 | return output 1277 | 1278 | # blocking 1279 | lower_limit = 0 1280 | upper_limit = 0 1281 | for i in range(nb): 1282 | upper_limit = upper_limit + self._blocksize 1283 | output[lower_limit:upper_limit,] = numpy.transpose(numpy.dot(x2, numpy.transpose(x1[lower_limit:upper_limit,]))) 1284 | self.KappaSqDis(output[lower_limit:upper_limit,], output[lower_limit:upper_limit,], dot_x1[lower_limit:upper_limit], dot_x2) 1285 | lower_limit = upper_limit 1286 | if lower_limit <= n1: 1287 | output[lower_limit:n1,] = numpy.transpose(numpy.dot(x2, numpy.transpose(x1[lower_limit:n1,]))) 1288 | self.KappaSqDis(output[lower_limit:n1,], output[lower_limit:n1,], dot_x1[lower_limit:n1], dot_x2) 1289 | 1290 | return output 1291 | 1292 | ## Compute the kernel between the data points in x1 and those in x2, 1293 | # then multiply the resulting kernel matrix by alpha2. 1294 | # It returns a matrix with entry $(ij)$ equal to 1295 | # $sum_r K(x1_i,x2_r) \times alpha2_r$. 1296 | # Other parameters are defined similarly as those in Dot. 1297 | # @param x1 [read] The first set of data points. 1298 | # @param x2 [read] The second set of data points. 1299 | # @param alpha2 [read] The set of coefficients. 1300 | # @param index1 [read] The indices into the first set of data points. 1301 | # @param index2 [read] The indices into the second set of data points. 1302 | # @param output [write] The buffer where the output matrix is written into. 1303 | # 1304 | def Expand(self, x1, x2, alpha2, index1=None, index2=None, output=None): 1305 | assert len(x1.shape) == 2, 'Argument 1 has wrong shape' 1306 | assert len(x2.shape) == 2, 'Argument 2 has wrong shape' 1307 | assert len(alpha2.shape) == 2, 'Argument 3 has wrong shape' 1308 | assert x1.shape[1] == x2.shape[1], \ 1309 | 'Argument 1 and 2 has different dimesions' 1310 | assert x2.shape[0] == alpha2.shape[0], \ 1311 | 'Argument 2 and 3 has different number of data points' 1312 | 1313 | # retrieve remembered data from cache. 1314 | flg1 = False 1315 | if self._cacheData.has_key(id(x1)): 1316 | dot_x1 = self._cacheData[id(x1)] 1317 | flg1 = True 1318 | flg2 = False 1319 | if self._cacheData.has_key(id(x2)): 1320 | dot_x2 = self._cacheData[id(x2)] 1321 | flg2 = True 1322 | 1323 | if index1 is not None: 1324 | x1 = x1[index1,] 1325 | if flg1 is True: 1326 | dot_x1 = dot_x1[index1,] 1327 | else: 1328 | dot_x1 = numpy.sum(x1**2, 1) 1329 | else: 1330 | if flg1 is False: 1331 | dot_x1 = numpy.sum(x1**2, 1) 1332 | if index2 is not None: 1333 | x2 = x2[index2,] 1334 | if flg2 is True: 1335 | dot_x2 = dot_x2[index2,] 1336 | else: 1337 | dot_x2 = numpy.sum(x2**2, 1) 1338 | alpha2 = alpha2[index2,] 1339 | else: 1340 | if flg2 is False: 1341 | dot_x2 = numpy.sum(x2**2, 1) 1342 | 1343 | n1 = x1.shape[0] 1344 | nb = n1 / self._blocksize 1345 | n2 = alpha2.shape[1] 1346 | 1347 | if output is None: 1348 | output = numpy.zeros((n1,n2), numpy.float64) 1349 | 1350 | # handle special cases. 1351 | if index2 is not None: 1352 | if len(index2) <= self._blocksize: 1353 | x1_x2 = numpy.dot(x1, numpy.transpose(x2)) 1354 | self.KappaSqDis(x1_x2, x1_x2, dot_x1, dot_x2) 1355 | output = numpy.dot(x1_x2,alpha2) 1356 | return output 1357 | 1358 | # blocking. 1359 | lower_limit = 0 1360 | upper_limit = 0 1361 | for i in range(nb): 1362 | upper_limit = upper_limit + self._blocksize 1363 | x1_x2 = numpy.transpose(numpy.dot(x2, numpy.transpose(x1[lower_limit:upper_limit,]))) 1364 | self.KappaSqDis(x1_x2, x1_x2, dot_x1[lower_limit:upper_limit], dot_x2) 1365 | output[lower_limit:upper_limit,] = numpy.dot(x1_x2, alpha2) 1366 | lower_limit = upper_limit 1367 | if lower_limit <= n1: 1368 | x1_x2 = numpy.transpose(numpy.dot(x2, numpy.transpose(x1[lower_limit:n1,]))) 1369 | self.KappaSqDis(x1_x2, x1_x2, dot_x1[lower_limit:n1], dot_x2) 1370 | output[lower_limit:n1,] = numpy.dot(x1_x2, alpha2) 1371 | 1372 | return output 1373 | 1374 | ## Compute the kernel between the data points in x1 and those in x2, 1375 | # then multiply the resulting kernel matrix elementwiesely by the 1376 | # the outer-product matrix between y1 and y2. It returns a matrix 1377 | # with entry $(ij)$ equal to $K(x1_i,x2_j) \times (y1_i \times y1_j)$. 1378 | # Other parameters are defined similarly as those in Dot. 1379 | # @param x1 [read] The first set of data points. 1380 | # @param y1 [read] The first set of labels. 1381 | # @param x2 [read] The second set of data points. 1382 | # @param y2 [read] The second set of labels. 1383 | # @param index1 [read] The indices into the first set of data points. 1384 | # @param index2 [read] The indices into the second set of data points. 1385 | # @param output [write] The buffer where the output matrix is written into. 1386 | # 1387 | def Tensor(self, x1, y1, x2, y2, index1=None, index2=None, output=None): 1388 | assert len(x1.shape) == 2, 'Argument 1 has wrong shape' 1389 | assert len(y1.shape) == 2, 'Argument 2 has wrong shape' 1390 | assert x1.shape[0] == y1.shape[0], \ 1391 | 'Argument 1 and 2 has different dimensions' 1392 | assert len(x2.shape) == 2, 'Argument 3 has wrong shape' 1393 | assert len(y2.shape) == 2, 'Argument 4 has wrong shape' 1394 | assert x2.shape[0] == y2.shape[0], \ 1395 | 'Argument 2 and 3 has different dimensions' 1396 | 1397 | # retrieve remembered data from the cache 1398 | flg1 = False 1399 | if self._cacheData.has_key(id(x1)): 1400 | dot_x1 = self._cacheData[id(x1)] 1401 | flg1 = True 1402 | flg2 = False 1403 | if self._cacheData.has_key(id(x2)): 1404 | dot_x2 = self._cacheData[id(x2)] 1405 | flg2 = True 1406 | 1407 | if index1 is not None: 1408 | x1 = x1[index1,] 1409 | if flg1 is True: 1410 | dot_x1 = dot_x1[index1,] 1411 | else: 1412 | dot_x1 = numpy.sum(x1**2, 1) 1413 | y1 = y1[index1,] 1414 | else: 1415 | if flg1 is False: 1416 | dot_x1 = numpy.sum(x1**2, 1) 1417 | if index2 is not None: 1418 | x2 = x2[index2,] 1419 | if flg2 is True: 1420 | dot_x2 = dot_x2[index2,] 1421 | else: 1422 | dot_x2 = numpy.sum(x2**2, 1) 1423 | y2 = y2[index2,] 1424 | else: 1425 | if flg2 is False: 1426 | dot_x2 = numpy.sum(x2**2, 1) 1427 | 1428 | n1 = x1.shape[0] 1429 | nb = n1 / self._blocksize 1430 | n2 = x2.shape[0] 1431 | 1432 | if output is None: 1433 | output = numpy.zeros((n1,n2), numpy.float64) 1434 | 1435 | # handle special cases: 1436 | if index2 is not None: 1437 | if len(index2) <= self._blocksize: 1438 | x1_x2 = numpy.dot(x1, numpy.transpose(x2)) 1439 | self.KappaSqDis(x1_x2, x1_x2, dot_x1, dot_x2) 1440 | output = numpy.transpose(y1[:,0] * numpy.transpose(y2[:,0] * x1_x2)) 1441 | return output 1442 | 1443 | # blocking 1444 | lower_limit = 0 1445 | upper_limit = 0 1446 | for i in range(nb): 1447 | upper_limit = upper_limit + self._blocksize 1448 | x1_x2 = numpy.transpose(numpy.dot(x2, numpy.transpose(x1[lower_limit:upper_limit,]))) 1449 | self.KappaSqDis(x1_x2, x1_x2, dot_x1[lower_limit:upper_limit], dot_x2) 1450 | output[lower_limit:upper_limit,] = numpy.transpose(y1[lower_limit:upper_limit,0] * numpy.transpose(y2[:,0] * x1_x2)) 1451 | lower_limit = upper_limit 1452 | if lower_limit <= n1: 1453 | x1_x2 = numpy.transpose(numpy.dot(x2, numpy.transpose(x1[lower_limit:n1,]))) 1454 | self.KappaSqDis(x1_x2, x1_x2, dot_x1[lower_limit:n1], dot_x2) 1455 | output[lower_limit:n1,] = numpy.transpose(y1[lower_limit:n1,0] * numpy.transpose(y2[:,0] * x1_x2)) 1456 | 1457 | return output 1458 | 1459 | ## Compute the kernel between the data points in x1 and those in x2, 1460 | # then multiply the resulting kernel matrix elementwiesely by the 1461 | # the outer-product matrix between y1 and y2, and final multiply 1462 | # the resulting matrix by alpha2. It returns a matrix with entry $(ij)$ 1463 | # equal to $sum_r K(x1_i,x2_r) \times (y1_i \times y1_r) \times alpha2_r$. 1464 | # Other parameters are defined similarly as those in Dot. 1465 | # @param x1 [read] The first set of data points. 1466 | # @param y1 [read] The first set of labels. 1467 | # @param x2 [read] The second set of data points. 1468 | # @param y2 [read] The second set of labels. 1469 | # @param index1 [read] The indices into the first set of data points. 1470 | # @param index2 [read] The indices into the second set of data points. 1471 | # @param output [write] The buffer where the output matrix is written into. 1472 | # 1473 | def TensorExpand(self, x1, y1, x2, y2, alpha2, index1=None, index2=None, output=None): 1474 | assert len(x1.shape) == 2, 'Argument 1 has wrong shape' 1475 | assert len(y1.shape) == 2, 'Argument 2 has wrong shape' 1476 | assert x1.shape[0] == y1.shape[0], \ 1477 | 'Argument 1 and 2 have different dimensions' 1478 | assert len(x2.shape) == 2, 'Argument 3 has wrong shape' 1479 | assert len(y2.shape) == 2, 'Argument 4 has wrong shape' 1480 | assert x2.shape[0] == y2.shape[0], \ 1481 | 'Argument 3 and 4 have different dimensions' 1482 | assert len(alpha2.shape) == 2, 'Argument 5 has wrong shape' 1483 | assert x2.shape[0] == alpha2.shape[0], \ 1484 | 'Argument 3 and 5 have different number of data points' 1485 | 1486 | # retrieve remembered data from the cache 1487 | flg1 = False 1488 | if self._cacheData.has_key(id(x1)): 1489 | dot_x1 = self._cacheData[id(x1)] 1490 | flg1 = True 1491 | flg2 = False 1492 | if self._cacheData.has_key(id(x2)): 1493 | dot_x2 = self._cacheData[id(x2)] 1494 | flg2 = True 1495 | 1496 | if index1 is not None: 1497 | x1 = x1[index1,] 1498 | if flg1 is True: 1499 | dot_x1 = dot_x1[index1,] 1500 | else: 1501 | dot_x1 = numpy.sum(x1**2, 1) 1502 | y1 = y1[index1,] 1503 | else: 1504 | if flg1 is False: 1505 | dot_x1 = numpy.sum(x1**2, 1) 1506 | 1507 | if index2 is not None: 1508 | x2 = x2[index2,] 1509 | if flg2 is True: 1510 | dot_x2 = dot_x2[index2,] 1511 | else: 1512 | dot_x2 = numpy.sum(x2**2, 1) 1513 | y2 = y2[index2,] 1514 | alpha2 = alpha2[index2,] 1515 | else: 1516 | if flg2 is False: 1517 | dot_x2 = numpy.sum(x2**2, 1) 1518 | 1519 | n1 = x1.shape[0] 1520 | nb = n1 / self._blocksize 1521 | n2 = alpha2.shape[1] 1522 | 1523 | if output is None: 1524 | output = numpy.zeros((n1,n2), numpy.float64) 1525 | 1526 | # handle special cases: 1527 | if index2 is not None: 1528 | if len(index2) <= self._blocksize: 1529 | x1_x2 = numpy.dot(x1, numpy.transpose(x2)) 1530 | self.KappaSqDis(x1_x2, x1_x2, dot_x1, dot_x2) 1531 | output = numpy.transpose(y1[:,0] * numpy.transpose(numpy.dot(y2[:,0]*x1_x2, alpha2))) 1532 | return output 1533 | 1534 | # blocking 1535 | lower_limit = 0 1536 | upper_limit = 0 1537 | for i in range(nb): 1538 | upper_limit = upper_limit + self._blocksize 1539 | x1_x2 = numpy.transpose(numpy.dot(x2, numpy.transpose(x1[lower_limit:upper_limit,]))) 1540 | self.KappaSqDis(x1_x2, x1_x2, dot_x1[lower_limit:upper_limit], dot_x2) 1541 | output[lower_limit:upper_limit,] = numpy.transpose(y1[lower_limit:upper_limit,0] * numpy.transpose(numpy.dot(y2[:,0]*x1_x2, alpha2))) 1542 | lower_limit = upper_limit 1543 | if lower_limit <= n1: 1544 | x1_x2 = numpy.transpose(numpy.dot(x2, numpy.transpose(x1[lower_limit:n1,]))) 1545 | self.KappaSqDis(x1_x2, x1_x2, dot_x1[lower_limit:n1], dot_x2) 1546 | output[lower_limit:n1,] = numpy.transpose(y1[lower_limit:n1,0] * numpy.transpose(numpy.dot(y2[:,0]*x1_x2, alpha2))) 1547 | 1548 | return output 1549 | 1550 | ## Create the cache for the base part of the kernel computed for 1551 | # data x, and index them by the id of x. If x have already been 1552 | # remembered, the old stored information is simply overwritten. 1553 | # @param x [read] The data whose base part is to be cached. 1554 | # 1555 | def CreateCacheKernel(self, x): 1556 | assert len(x.shape) == 2, 'Argument 1 has wrong shape' 1557 | n = x.shape[0] 1558 | nb = n / self._blocksize 1559 | 1560 | # create the cache space 1561 | if self._cacheKernel.has_key(id(x)): 1562 | self.ClearCacheKernel(x) 1563 | tmpCacheKernel = numpy.zeros((n,n), numpy.float64) 1564 | self._cacheKernel[id(x)] = tmpCacheKernel 1565 | 1566 | if self._cacheData.has_key(id(x)): 1567 | dot_x = self._cacheData[id(x)] 1568 | else: 1569 | dot_x = numpy.sum(x**2,1) 1570 | 1571 | # blocking 1572 | lower_limit = 0 1573 | upper_limit = 0 1574 | for i in range(nb): 1575 | upper_limit = upper_limit + self._blocksize 1576 | tmpCacheKernel[lower_limit:upper_limit,] = numpy.transpose(numpy.dot(x, numpy.transpose(x[lower_limit:upper_limit,]))) 1577 | tmpCacheKernel[lower_limit:upper_limit,] = numpy.add.outer(dot_x[lower_limit:upper_limit], dot_x) \ 1578 | - 2*tmpCacheKernel[lower_limit:upper_limit,] 1579 | lower_limit = upper_limit 1580 | if lower_limit <= n: 1581 | tmpCacheKernel[lower_limit:n,] = numpy.transpose(numpy.dot(x, numpy.transpose(x[lower_limit:n,]))) 1582 | tmpCacheKernel[lower_limit:n,] = numpy.add.outer(dot_x[lower_limit:n], dot_x) \ 1583 | - 2*tmpCacheKernel[lower_limit:n,] 1584 | 1585 | return True 1586 | 1587 | ## Dot product of x with itself with the cached base part of the kernel. 1588 | # If param is given, the kernel matrix is computed using 1589 | # the given parameter and the current base part. Otherwise, the old 1590 | # parameters are used. 1591 | # @param x The data set. 1592 | # @param param The new parameters. 1593 | # @param output The output buffer. 1594 | # 1595 | def DotCacheKernel(self, x, param=None, output=None): 1596 | assert len(x.shape)==2, 'Argument 1 has wrong shape' 1597 | assert self._cacheKernel.has_key(id(x)) == True, \ 1598 | 'Argument 1 has not been cached' 1599 | 1600 | n = x.shape[0] 1601 | nb = n / self._blocksize 1602 | tmpCacheKernel = self._cacheKernel[id(x)] 1603 | 1604 | # set parameters. 1605 | if param is not None: 1606 | self.SetParam(param) 1607 | 1608 | if output is None: 1609 | output = numpy.zeros((n,n), numpy.float64) 1610 | 1611 | # blocking 1612 | lower_limit = 0 1613 | upper_limit = 0 1614 | for i in range(nb): 1615 | upper_limit = upper_limit + self._blocksize 1616 | output[lower_limit:upper_limit,] = self.Kappa(tmpCacheKernel[lower_limit:upper_limit,]) 1617 | lower_limit = upper_limit 1618 | if lower_limit <= n: 1619 | output[lower_limit:n,] = self.Kappa(tmpCacheKernel[lower_limit:n,]) 1620 | 1621 | return output 1622 | 1623 | ## Decrement the base part of the kernel for x1 stored in the cache 1624 | # by x2. Note that this method updates the cache for the kernel part. 1625 | # @param x1 The data set whose base part has been cached. 1626 | # @param x2 The data set who is to be decremented from x1. 1627 | # 1628 | def DecCacheKernel(self, x1, x2): 1629 | assert len(x1.shape) == 2, 'Argument 1 has wrong shape' 1630 | assert len(x2.shape) == 2, 'Argument 2 has wrong shape' 1631 | assert x1.shape[0] == x2.shape[0], \ 1632 | 'Argument 1 and 2 have different number of data points' 1633 | assert self._cacheKernel.has_key(id(x1)) == True, \ 1634 | 'Argument 1 has not been cached' 1635 | 1636 | n = x1.shape[0] 1637 | nb = n / self._blocksize 1638 | tmpCacheKernel = self._cacheKernel[id(x1)] 1639 | 1640 | if self._cacheData.has_key(id(x2)): 1641 | dot_x2 = self._cacheData[id(x2)] 1642 | else: 1643 | dot_x2 = numpy.sum(x2**2,1) 1644 | 1645 | # blocking 1646 | lower_limit = 0 1647 | upper_limit = 0 1648 | for i in range(nb): 1649 | upper_limit = upper_limit + self._blocksize 1650 | x2_x2 = numpy.transpose(numpy.dot(x2, numpy.transpose(x2[lower_limit:upper_limit,]))) 1651 | tmpCacheKernel[lower_limit:upper_limit,] = tmpCacheKernel[lower_limit:upper_limit,] \ 1652 | + 2*x2_x2 \ 1653 | - numpy.add.outer(dot_x2[lower_limit:upper_limit], dot_x2) 1654 | lower_limit = upper_limit 1655 | if lower_limit <= n: 1656 | x2_x2 = numpy.transpose(numpy.dot(x2, numpy.transpose(x2[lower_limit:n,]))) 1657 | tmpCacheKernel[lower_limit:n,] = tmpCacheKernel[lower_limit:n,] \ 1658 | + 2*x2_x2 \ 1659 | - numpy.add.outer(dot_x2[lower_limit:n], dot_x2) 1660 | 1661 | return True 1662 | 1663 | ## Decrement the base part of the kernel for x1 stored in the cache 1664 | # by x2, and return the resulting kernel matrix. If param is given, 1665 | # the kernel matrix is computed using the given parameter and the 1666 | # current base part. Otherwise, the old parameters are used. Note 1667 | # that this method does NOT change the cache for the kernel part. 1668 | # @param x1 The data set whose base part has been cached. 1669 | # @param x2 The data set who is to be decremented from x1. 1670 | # @param param The new parameters. 1671 | # 1672 | def DecDotCacheKernel(self, x1, x2, param=None, output=None): 1673 | assert len(x1.shape) == 2, 'Argument 1 has wrong shape' 1674 | assert len(x2.shape) == 2, 'Argument 2 has wrong shape' 1675 | assert x1.shape[0] == x2.shape[0], \ 1676 | 'Argument 1 and 2 have different number of data points' 1677 | assert self._cacheKernel.has_key(id(x1)) == True, \ 1678 | 'Argument 1 has not been cached' 1679 | 1680 | n = x1.shape[0] 1681 | nb = n / self._blocksize 1682 | tmpCacheKernel = self._cacheKernel[id(x1)] 1683 | 1684 | # set parameters. 1685 | if param is not None: 1686 | self.SetParam(param) 1687 | 1688 | if output is None: 1689 | output = numpy.zeros((n,n), numpy.float64) 1690 | 1691 | if self._cacheData.has_key(id(x2)): 1692 | dot_x2 = self._cacheData[id(x2)] 1693 | else: 1694 | dot_x2 = numpy.sum(x2*x2,1) 1695 | 1696 | # blocking 1697 | lower_limit = 0 1698 | upper_limit = 0 1699 | for i in range(nb): 1700 | upper_limit = upper_limit + self._blocksize 1701 | output[lower_limit:upper_limit,] = numpy.transpose(numpy.dot(x2, numpy.transpose(x2[lower_limit:upper_limit,]))) 1702 | output[lower_limit:upper_limit,] = self.Kappa(tmpCacheKernel[lower_limit:upper_limit,] \ 1703 | + 2*output[lower_limit:upper_limit,] \ 1704 | - numpy.add.outer(dot_x2[lower_limit:upper_limit], dot_x2)) 1705 | lower_limit = upper_limit 1706 | if lower_limit <= n: 1707 | output[lower_limit:n,] = numpy.transpose(numpy.dot(x2, numpy.transpose(x2[lower_limit:n,]))) 1708 | output[lower_limit:n,] = self.Kappa(tmpCacheKernel[lower_limit:n,] \ 1709 | + 2*output[lower_limit:n,] \ 1710 | - numpy.add.outer(dot_x2[lower_limit:n], dot_x2)) 1711 | 1712 | return output 1713 | 1714 | ## Gradient of the kernel matrix with respect to the kernel parameter. 1715 | # If param is given, the kernel matrix is computed using the given 1716 | # parameter and the current base part. Otherwise, the old parameters 1717 | # are used. 1718 | # @param x The data set for the kernel matrix. 1719 | # @param param The kernel parameters. 1720 | # 1721 | def GradDotCacheKernel(self, x, param=None, output=None): 1722 | assert len(x.shape) == 2, "Argument 1 has wrong shape" 1723 | assert self._cacheKernel.has_key(id(x)) == True, \ 1724 | "Argument 1 has not been cached" 1725 | 1726 | n = x.shape[0] 1727 | nb = n / self._blocksize 1728 | tmpCacheKernel = self._cacheKernel[id(x)] 1729 | 1730 | if param is not None: 1731 | self.SetParam(param) 1732 | 1733 | if output is None: 1734 | output = numpy.zeros((n,n), numpy.float64) 1735 | 1736 | # blocking 1737 | lower_limit = 0 1738 | upper_limit = 0 1739 | for i in range(nb): 1740 | upper_limit = upper_limit + self._blocksize 1741 | output[lower_limit:upper_limit,] = self.KappaGrad(tmpCacheKernel[lower_limit:upper_limit,]) 1742 | lower_limit = upper_limit 1743 | if lower_limit <= n: 1744 | output[lower_limit:n,] = self.KappaGrad(tmpCacheKernel[lower_limit:n,]) 1745 | 1746 | return output 1747 | 1748 | 1749 | ## Gauss kernel 1750 | # 1751 | # Kernel of the form: $K(x1,x2)=\exp(-scale*\|x1-x2\|^2)$. 1752 | # This is implemented by the Kappa function. 1753 | # 1754 | class CGaussKernel(CRBFKernel): 1755 | def __init__(self, scale=1.0, blocksize=128): 1756 | CRBFKernel.__init__(self, blocksize) 1757 | self._name = 'Gauss kernel' 1758 | if scale < 0.0: 1759 | raise CElefantConstraintException(scale, "param must not be negative") 1760 | self._scale = scale 1761 | self._typicalParam = 10**(numpy.arange(10)-7.0) 1762 | 1763 | ## Method that operates on the base part of the kernel to 1764 | # generate the new kernel 1765 | # @param x Base part of the kernel matrix. 1766 | # 1767 | def Kappa(self, x): 1768 | return numpy.exp(-self._scale * x) 1769 | 1770 | ## Gradient of the kernel with respect to the kernel 1771 | # parameter evaluated at the base part x of the kernel. 1772 | # @param x Base part of the kernel. 1773 | # 1774 | def KappaGrad(self, x): 1775 | return -x * numpy.exp(-self._scale * x) 1776 | 1777 | ## Function that set the parameter of the kernel. 1778 | # @param param Parameters to be set. 1779 | # 1780 | def SetParam(self, param): 1781 | if param < 0.0: 1782 | raise CElefantConstraintException(param, "param must not be negative") 1783 | self._scale = param 1784 | 1785 | ## Laplace Kernel 1786 | # 1787 | # Kernel of the form: $K(x1,x2)=\exp(-scale*\|x1-x2\|)$. 1788 | # This is implemented by the Kappa function. 1789 | # 1790 | class CLaplaceKernel(CRBFKernel): 1791 | def __init__(self, scale=1.0, blocksize=128): 1792 | CRBFKernel.__init__(self, blocksize) 1793 | self._name = 'Laplace kernel' 1794 | if scale < 0.0: 1795 | raise CElefantConstraintException(scale, "param must not be negative") 1796 | self._scale = scale 1797 | self._typicalParam = 10**(numpy.arange(10)-7.0) 1798 | 1799 | ## Method that operates on the base part of the kernel to 1800 | # generate the new kernel 1801 | # @param x Base part of the kernel matrix. 1802 | # 1803 | def Kappa(self, x): 1804 | return numpy.exp(-self._scale * numpy.sqrt(x.clip(min = 0.0, max = numpy.inf))) 1805 | 1806 | ## Gradient of the kernel with respect to the kernel 1807 | # parameter evaluated at the base part x of the kernel. 1808 | # @param x Base part of the kernel. 1809 | # 1810 | def KappaGrad(self, x): 1811 | tmp = numpy.sqrt(x.clip(min = 0.0, max = numpy.inf)) 1812 | return -tmp * numpy.exp(-self._scale * tmp) 1813 | 1814 | ## Function that set the parameter of the kernel. 1815 | # @param param Parameters to be set. 1816 | # 1817 | def SetParam(self, param): 1818 | # Enforce nonnegativity of parameter 1819 | # assert param >= 0.0, 'param must not be negative' 1820 | if param < 0.0: 1821 | raise CElefantConstraintException(param, "param must not be negative") 1822 | self._scale = param 1823 | 1824 | ## Inverse square distance kernel 1825 | # 1826 | # Kernel of the form: $K(x1,x2)=\frac{1}{\|x1-x2\|^2} 1827 | # This is implemented by the Kappa function. Note that 1828 | # if the distance between x1 and x2 is very small, the 1829 | # kernel is computed as zero. 1830 | # 1831 | class CInvSqDisKernel(CRBFKernel): 1832 | def __init__(self, blocksize=128, epsilon = 1.0e-6): 1833 | CRBFKernel.__init__(self, blocksize) 1834 | self._name = 'Inverse Square Distance kernel' 1835 | self._epsilon = epsilon 1836 | 1837 | 1838 | ## Method that operates on the base part of the kernel to 1839 | # generate the new kernel 1840 | # @param x Base part of the kernel matrix. 1841 | # 1842 | def Kappa(self, x): 1843 | return 1.0 / (x + self._epsilon) 1844 | 1845 | ## Inverse distance kernel 1846 | # 1847 | # Kernel of the form: $K(x1,x2)=\frac{1}{\|x1-x2\|} 1848 | # This is implemented by the Kappa function. Note that 1849 | # if the distance between x1 and x2 is very small, the 1850 | # kernel is computed as zero. 1851 | # 1852 | class CInvDisKernel(CRBFKernel): 1853 | def __init__(self, blocksize=128, epsilon = 1.0e-6): 1854 | CRBFKernel.__init__(self, blocksize) 1855 | self._name = 'Inverse Distance kernel' 1856 | self._epsilon = epsilon 1857 | 1858 | ## Method that operates on the base part of the kernel to 1859 | # generate the new kernel 1860 | # @param x Base part of the kernel matrix. 1861 | # 1862 | def Kappa(self, x): 1863 | return 1.0/numpy.sqrt(x + self._epsilon) 1864 | 1865 | #------------------------------------------------------------------------------ 1866 | 1867 | ## Delta kernel class 1868 | # 1869 | # The methods are implemente efficiently by computing the resulting 1870 | # matrices block by block. Currently this class only works for the 1871 | # case where the inputs are integer. 1872 | # 1873 | class CDeltaKernel(CVectorKernel): 1874 | def __init__(self, blocksize=128): 1875 | CVectorKernel.__init__(self, blocksize) 1876 | self._name = 'Delta kernel' 1877 | 1878 | ## Compute the kernel between two data points x1 and x2. 1879 | # It returns a value 1 if x1 and x2 are equal, otherwise 0. 1880 | # @param x1 [read] The first data point. 1881 | # @param x2 [read] The second data point. 1882 | # 1883 | def K(self, x1, x2): 1884 | assert len(x1.squeeze().shape) == 1, 'x1 is not a vector' 1885 | assert len(x2.squeeze().shape) == 1, 'x2 is not a vector' 1886 | return numpy.equal.outer(x1.squeeze(), x2.squeeze()).astype(numpy.int) 1887 | 1888 | ## Compute the kernel between the data points in x1 and those in x2. 1889 | # It returns a matrix with entry $(ij)$ equal to $K(x1_i, x1_j)$. 1890 | # If index1/index2 is 1891 | # specified, only those data points in x1/x2 with indices corresponding 1892 | # to index1/index2 are used to compute the kernel matrix. Furthermore, 1893 | # if output is specified, the provided buffer is used explicitly to 1894 | # store the kernel matrix. 1895 | # @param x1 [read] The first set of data points. 1896 | # @param x2 [read] The second set of data points. 1897 | # @param index1 [read] The indices into the first set of data points. 1898 | # @param index2 [read] The indices into the second set of data points. 1899 | # @param output [write] The buffer where the output matrix is written into. 1900 | # 1901 | def Dot(self, x1, x2, index1=None, index2=None, output=None): 1902 | assert len(x1.shape) == 2, 'Argument 1 has wrong shape' 1903 | assert len(x2.shape) == 2, 'Argument 2 has wrong shape' 1904 | assert x1.shape[0] == x2.shape[0], \ 1905 | 'Argument 1 and Argument 2 have different dimensions' 1906 | 1907 | if index1 is not None: 1908 | x1 = x1[index1,] 1909 | if index2 is not None: 1910 | x2 = x2[index2,] 1911 | 1912 | # number of data points in x1. 1913 | n1 = x1.shape[0] 1914 | # number of data points in x2. 1915 | n2 = x2.shape[0] 1916 | # number of blocks. 1917 | nb = n1 / self._blocksize 1918 | 1919 | if output is None: 1920 | output = numpy.zeros((n1,n2), numpy.int) 1921 | 1922 | # handle special cases: 1923 | if index2 is not None: 1924 | if len(index2) <= self._blocksize: 1925 | output = numpy.equal.outer(x1.squeeze(), x2.squeeze()).astype(numpy.int) 1926 | return output 1927 | 1928 | # blocking 1929 | lower_limit = 0 1930 | upper_limit = 0 1931 | for i in range(nb): 1932 | upper_limit = upper_limit + self._blocksize 1933 | output[lower_limit:upper_limit,] = numpy.equal.outer(x1[lower_limit:upper_limit,].squeeze(), x2.squeeze()).astype(numpy.int) 1934 | lower_limit = upper_limit 1935 | if lower_limit <= n1: 1936 | output[lower_limit:n1,] = numpy.equal.outer(x1[lower_limit:n1,].squeeze(), x2.squeeze()).astype(numpy.int) 1937 | 1938 | return output 1939 | 1940 | #------------------------------------------------------------------------------ 1941 | 1942 | ## Joint kernel class for k(x,x')l(y,y') 1943 | # 1944 | # The methods are implemente efficiently by computing the resulting 1945 | # matrices block by block. Currently this class only works for the 1946 | # case where the inputs are integer. 1947 | # 1948 | class CJointKernel(CVectorKernel): 1949 | def __init__(self, y, xkernel=CLinearKernel(), ykernel=CDeltaKernel(), blocksize=128): 1950 | CVectorKernel.__init__(self, blocksize) 1951 | self._name = 'Joint kernel' 1952 | self.xkernel = xkernel 1953 | self.ykernel = ykernel 1954 | # remember the kernel matrix on y. 1955 | assert y is not None, 'y has be to provided for the initialization' 1956 | self.kyy = self.ykernel.Dot(y,y) 1957 | 1958 | ## Compute the kernel between the data points in x1 and those in x2, 1959 | # then multiply the resulting kernel matrix by alpha2. 1960 | # It returns a matrix with entry $(ij)$ equal to 1961 | # $sum_r K(x1_i,x2_r) \times alpha2_r$. 1962 | # Other parameters are defined similarly as those in Dot. 1963 | # @param x1 [read] The first set of data points. 1964 | # @param x2 [read] The second set of data points. 1965 | # @param alpha2 [read] The set of coefficients. 1966 | # @param index1 [read] The indices into the first set of data points. 1967 | # @param index2 [read] The indices into the second set of data points. 1968 | # @param output [write] The buffer where the output matrix is written into. 1969 | # 1970 | def Expand(self, x1, x2, alpha2, index1=None, index2=None, output=None): 1971 | assert len(x1.shape) == 2, 'Argument 1 has wrong shape' 1972 | assert len(x2.shape) == 2, 'Argument 2 has wrong shape' 1973 | assert len(alpha2.shape) == 2, 'Argument 3 has wrong shape' 1974 | assert x1.shape[1] == x2.shape[1], \ 1975 | 'Argument 1 and 2 has different dimesions' 1976 | assert x2.shape[0] == alpha2.shape[0], \ 1977 | 'Argument 2 and 3 has different number of data points' 1978 | 1979 | L = self.kyy 1980 | if index1 is not None: 1981 | x1 = x1[index1,] 1982 | L = L[index1,] 1983 | if index2 is not None: 1984 | x2 = x2[index2,] 1985 | alpha2 = alpha2[index2,] 1986 | L = L[:,index2] 1987 | 1988 | n1 = x1.shape[0] 1989 | nb = n1 / self._blocksize 1990 | n2 = alpha2.shape[1] 1991 | 1992 | if output is None: 1993 | output = numpy.zeros((n1,n2), numpy.float64) 1994 | 1995 | output = numpy.transpose(numpy.dot(L, self.xkernel.Expand(x1, x2, alpha2))) 1996 | return output 1997 | 1998 | if __name__== '__main__': 1999 | n = 5000 2000 | x = numpy.random.rand(n,1) 2001 | y = (numpy.random.rand(n,1)*10).astype(numpy.int) 2002 | alpha = numpy.random.rand(n,4) 2003 | import time 2004 | t1 = time.clock() 2005 | kernel = CJointKernel(y) 2006 | K = kernel.Expand(x, x, alpha) 2007 | t2 = time.clock() 2008 | print K.shape, t2-t1 2009 | --------------------------------------------------------------------------------