-
Notifications
You must be signed in to change notification settings - Fork 347
replace and improve integration tests #477
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
2e45b77
751d31b
2e61716
2eaea31
ae4be24
ae6dbd3
9d139f7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1002,6 +1002,9 @@ public func convolve( | |
| if weightSize % 2 == 1 { | ||
| padding = weightSize / 2 | ||
| } else { | ||
| // even sized weights use asymmetric padding -- this must match | ||
| // python's `mx.convolve()` so that the result is the centered | ||
| // `input.size` window of the full convolution | ||
| let padLeft = weightSize / 2 | ||
| let padRight = max(0, padLeft - 1) | ||
|
|
||
|
|
@@ -2184,7 +2187,7 @@ public func multiply( | |
| /// - <doc:arithmetic> | ||
| public func nanToNum( | ||
| _ array: MLXArray, | ||
| nan: Float = 0, posInf: Float? = 0, negInf: Float? = 0, | ||
| nan: Float = 0, posInf: Float? = nil, negInf: Float? = nil, | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. use mlx default values for nanToNum +/- infinity |
||
| stream: StreamOrDevice = .default | ||
| ) -> MLXArray { | ||
| let posInf = mlx_optional_float(value: posInf ?? 0, has_value: posInf != nil) | ||
|
|
@@ -3110,15 +3113,15 @@ public func tanh(_ array: MLXArray, stream: StreamOrDevice = .default) -> MLXArr | |
| /// - Parameters: | ||
| /// - a: input array | ||
| /// - b: input array | ||
| /// - axes: sum over the last `axes` dimensions | ||
| /// - axes: sum over the last `axes` dimensions of `a` and the first `axes` of `b` | ||
| /// - stream: stream or device to evaluate on | ||
| /// - Returns: tensor dot product | ||
| /// | ||
| /// ### See Also | ||
| /// - <doc:arithmetic> | ||
| /// - ``tensordot(_:_:axes:stream:)-(MLXArray,MLXArray,Int,StreamOrDevice)`` | ||
| public func tensordot( | ||
| _ a: MLXArray, _ b: MLXArray, axes: Int = 1, stream: StreamOrDevice = .default | ||
| _ a: MLXArray, _ b: MLXArray, axes: Int = 2, stream: StreamOrDevice = .default | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. tensorDot axes default 1 -> 2 (matches python) |
||
| ) -> MLXArray { | ||
| var result = mlx_array_new() | ||
| mlx_tensordot_axis(&result, a.ctx, b.ctx, axes.int32, stream.ctx) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -41,9 +41,10 @@ open class Pool: Module, UnaryLayer { | |
|
|
||
| // Apply padding if any padding value is greater than 0 | ||
| if padding.contains(where: { $0 > 0 }) { | ||
| // batch and channel dimension get no padding | ||
| let padWidths: [IntOrPair] = | ||
| [0, 0] + padding.map { .init($0) } + [0, 0] | ||
| // one width per dimension: batch and channel get no padding, each | ||
| // spatial dimension is padded symmetrically (`IntOrPair` is already | ||
| // the (before, after) pair for a single dimension) | ||
| let padWidths: [IntOrPair] = [0] + padding.map { IntOrPair($0) } + [0] | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. MLXNN Pooling padWidths matches python |
||
| let paddingValue = paddingValue.asMLXArray(dtype: input.dtype) | ||
| input = padded(input, widths: padWidths, mode: .constant, value: paddingValue) | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -156,19 +156,41 @@ final public class ALiBi: Module { | |
| public override init() { | ||
| } | ||
|
|
||
| /// The per-head slopes, matching python's `ALiBi.create_alibi_slope()`. | ||
| /// | ||
| /// For a power of two head count the slopes are `2^(-8i/n)` for `i` in | ||
| /// `1...n`. Otherwise python uses the slopes of the next power of two *below* | ||
| /// `n` and pads them with every other slope of the next power of two *above*, | ||
| /// which is not the same as extending the geometric series. | ||
| static func alibiSlope(numHeads: Int) -> MLXArray { | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. MLXNN Alibi slope function matches python |
||
| let x = pow(pow(2, 8), (1 / Float(numHeads))) | ||
| let out = pow(x, -MLXArray(1 ..< (numHeads + 1))) | ||
| return out.expandedDimensions(axes: [-1, -2]) | ||
| func slopes(_ n: Int) -> [Float] { | ||
| let log2n = Foundation.log2(Double(n)) | ||
| if log2n == log2n.rounded(.down) { | ||
| let start = Foundation.pow(2.0, -Foundation.pow(2.0, 3 - log2n)) | ||
| return (1 ... n).map { Float(Foundation.pow(start, Double($0))) } | ||
| } | ||
|
|
||
| let closestPowerOf2 = Int(Foundation.pow(2.0, log2n.rounded(.down))) | ||
| let interleaved = slopes(2 * closestPowerOf2) | ||
| .enumerated() | ||
| .filter { $0.offset.isMultiple(of: 2) } | ||
| .map { $0.element } | ||
| .prefix(n - closestPowerOf2) | ||
| return slopes(closestPowerOf2) + interleaved | ||
| } | ||
|
|
||
| return MLXArray(slopes(numHeads)).expandedDimensions(axes: [-1, -2]) | ||
| } | ||
|
|
||
| static func alibiMatrix(key: Key) -> MLXArray { | ||
| if let value = cache[key] { | ||
| return value | ||
| } | ||
|
|
||
| // x1 is a column and x2 a row so that the difference is the (q, k) | ||
| // distance matrix -- python: `x1[:, None] - x2[None, :]` | ||
| let x1 = MLXArray(key.offset ..< key.qSequenceLength).expandedDimensions(axis: 1) | ||
| let x2 = MLXArray(0 ..< key.kSequenceLength).expandedDimensions(axis: 1) | ||
| let x2 = MLXArray(0 ..< key.kSequenceLength).expandedDimensions(axis: 0) | ||
| let distanceMatrix = -abs(expandedDimensions((x1 - x2), axes: [0, 1])) | ||
|
|
||
| let slope = alibiSlope(numHeads: key.numHeads) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
convolve .same padding side matches python