Skip to content

Commit b48a5e5

Browse files
Merge branch 'main' into unit
2 parents 6dfe886 + 78372a1 commit b48a5e5

File tree

7 files changed

+73
-31
lines changed

7 files changed

+73
-31
lines changed

RELEASENOTES.md

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,28 @@
22

33
Releases, starting with 9/2/2021, are listed with the most recent release at the top.
44

5-
65
# NuGet Version 0.104.0
76

87
This is a big change in implementation, but not as big in API surface area. Many of the builtin modules, but not all, were re-implemented in managed code calling into native code via the functional APIs. This has several advantages:
98

10-
1. Align with the Pytorch implementations.
11-
2. More easily expose module attributes as properties as Pytorch does.
12-
3. In some cases, avoid native code altogether.
13-
4. The builtin modules can serve as "best practice" examples for custom module authors.
9+
1. Align with the Pytorch implementations.<br/>
10+
2. More easily expose module attributes as properties as Pytorch does.<br/>
11+
3. In some cases, avoid native code altogether.<br/>
12+
4. The builtin modules can serve as "best practice" examples for custom module authors.<br/>
1413

1514
__Breaking Changes__:
1615

1716
The names of several arguments have been changed to align better with Pytorch naming. This may break code that passes such arguments by name, but will be caught at compile time.
1817

18+
The argument defaults for `torch.diagonal()` and `Tensor.diagonal()` arguments have been corrected.
19+
1920
__Issues fixed__:
2021

2122
#1397 Look into whether parameter creation from a tensor leads to incorrect dispose scope statistics. This bug was discovered during testing of the PR.<br/>
2223
#1210 Attribute omissions.<br/>
24+
#1210 Attribute omissions.<br/>
25+
#1400 There may be an error in torchvision.transforms.GaussianBlur<br/>
26+
#1402 diagonal() has incorrect default<br/>
2327

2428
# NuGet Version 0.103.1
2529

src/TorchSharp/LinearAlgebra.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,8 @@ public static (Tensor, Tensor) slogdet(Tensor input)
136136
/// </summary>
137137
/// <param name="input">The input tensor</param>
138138
/// <param name="offset">Which diagonal to consider. Default: 0 (main diagonal).</param>
139-
/// <param name="dim1">First dimension with respect to which to take diagonal. Default: -1.</param>
140-
/// <param name="dim2">Second dimension with respect to which to take diagonal. Default: -2.</param>
139+
/// <param name="dim1">First dimension with respect to which to take diagonal. Default: -2.</param>
140+
/// <param name="dim2">Second dimension with respect to which to take diagonal. Default: -1.</param>
141141
/// <remarks>
142142
/// Applying torch.diag_embed() to the output of this function with the same arguments yields a diagonal matrix with the diagonal entries of the input.
143143
/// However, torch.diag_embed() has different default dimensions, so those need to be explicitly specified.

src/TorchSharp/Tensor/Tensor.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3399,8 +3399,9 @@ public Tensor diagflat(long offset = 0)
33993399
/// Applying torch.diag_embed() to the output of this function with the same arguments yields a diagonal matrix with the diagonal entries of the input.
34003400
/// However, torch.diag_embed() has different default dimensions, so those need to be explicitly specified.
34013401
/// </remarks>
3402-
public Tensor diagonal(long offset = 0, long dim1 = 0, long dim2 = 0)
3402+
public Tensor diagonal(long offset = 0L, long dim1 = 0L, long dim2 = 1L)
34033403
{
3404+
if (dim1 == dim2) throw new ArgumentException($"Diagonal dimensions cannot be identical {dim1}, {dim2}");
34043405
var res = NativeMethods.THSTensor_diagonal(Handle, offset, dim1, dim2);
34053406
if (res == IntPtr.Zero) { CheckForErrors(); }
34063407
return new Tensor(res);

src/TorchSharp/Tensor/torch.OtherOperations.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ public static Tensor diag_embed(Tensor input, long offset = 0L, long dim1 = -2L,
314314
/// Applying torch.diag_embed() to the output of this function with the same arguments yields a diagonal matrix with the diagonal entries of the input.
315315
/// However, torch.diag_embed() has different default dimensions, so those need to be explicitly specified.
316316
/// </remarks>
317-
public static Tensor diagonal(Tensor input, long offset = 0, long dim1 = 0, long dim2 = 0) => input.diagonal(offset, dim1, dim2);
317+
public static Tensor diagonal(Tensor input, long offset = 0L, long dim1 = 0L, long dim2 = 1L) => input.diagonal(offset, dim1, dim2);
318318

319319
// https://pytorch.org/docs/stable/generated/torch.diff
320320
/// <summary>

src/TorchVision/Functional.cs

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -443,24 +443,25 @@ public static Tensor erase(Tensor img, int top, int left, int height, int width,
443443
/// The image is expected to have […, H, W] shape, where … means an arbitrary number of leading dimensions.
444444
/// </summary>
445445
/// <returns></returns>
446-
public static Tensor gaussian_blur(Tensor input, IList<long> kernelSize, IList<float> sigma)
446+
public static Tensor gaussian_blur(Tensor input, IList<long> kernelSize, ReadOnlySpan<float> sigma)
447447
{
448448
var dtype = torch.is_integral(input.dtype) ? ScalarType.Float32 : input.dtype;
449449

450450
if (kernelSize.Count == 1) {
451451
kernelSize = new long[] { kernelSize[0], kernelSize[0] };
452452
}
453453

454-
if (sigma == null) {
454+
if (sigma == null || sigma.Length == 0)
455+
{
455456
sigma = new float[] {
456-
0.3f * ((kernelSize[0] - 1) * 0.5f - 1) + 0.8f,
457-
0.3f * ((kernelSize[1] - 1) * 0.5f - 1) + 0.8f,
458-
};
459-
} else if (sigma.Count == 1) {
457+
0.3f * ((kernelSize[0] - 1) * 0.5f - 1) + 0.8f,
458+
0.3f * ((kernelSize[1] - 1) * 0.5f - 1) + 0.8f,
459+
};
460+
} else if (sigma.Length == 1) {
460461
sigma = new float[] {
461-
sigma[0],
462-
sigma[0],
463-
};
462+
sigma[0],
463+
sigma[0],
464+
};
464465
}
465466
using var t0 = GetGaussianKernel2d(kernelSize, sigma, dtype, input.device);
466467
using var kernel = t0.expand(input.shape[input.shape.Length - 3], 1, t0.shape[0], t0.shape[1]);
@@ -755,7 +756,7 @@ public static Tensor resized_crop(Tensor input, int top, int left, int height, i
755756
throw new ArgumentException("Crop dimensions exceed image size.", nameof(input));
756757
break;
757758
default: // Any number of batch dimensions
758-
if (top + height > input.shape[input.ndim-2] || left + width > input.shape[input.ndim-1])
759+
if (top + height > input.shape[input.ndim-2] || left + width > input.shape[input.ndim-1])
759760
throw new ArgumentException("Crop dimensions exceed image size.", nameof(input));
760761
break;
761762
case 1:
@@ -891,7 +892,7 @@ private static Tensor GetGaussianKernel1d(long size, float sigma)
891892
return pdf / sum;
892893
}
893894

894-
private static Tensor GetGaussianKernel2d(IList<long> kernelSize, IList<float> sigma, ScalarType dtype, torch.Device device)
895+
private static Tensor GetGaussianKernel2d(IList<long> kernelSize, ReadOnlySpan<float> sigma, ScalarType dtype, torch.Device device)
895896
{
896897
using var tX1 = GetGaussianKernel1d(kernelSize[0], sigma[0]);
897898
using var tX2 = tX1.to(dtype, device);

src/TorchVision/GaussianBlur.cs

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,29 +9,44 @@ namespace TorchSharp
99
{
1010
public static partial class torchvision
1111
{
12-
internal class GaussianBlur : ITransform
12+
internal class GaussianBlur : torch.nn.Module<Tensor,Tensor>, ITransform
1313
{
14-
internal GaussianBlur(IList<long> kernelSize, float min, float max)
14+
internal GaussianBlur(IList<long> kernelSize, float sigma): base(nameof(GaussianBlur))
1515
{
1616
if (kernelSize == null || kernelSize.Count != 2 || kernelSize.Any(x => x <= 0)) {
1717
throw new ArgumentException("Invalid kernel size argument.");
1818
}
19-
if (min < 0 || max < 0 || min >= max) {
20-
throw new ArgumentException("Invalid GaussianBlur arguments.");
19+
if (sigma <= 0) {
20+
throw new ArgumentException("Invalid GaussianBlur arguments: sigma must be positive.");
2121
}
22-
this.sigma = (min == max) ?
23-
min :
24-
(float)(new Random().NextDouble() * (max - min) + min);
22+
this.sigma = sigma;
2523
this.kernelSize = kernelSize.ToArray();
2624
}
2725

28-
public Tensor call(Tensor input)
26+
internal GaussianBlur(IList<long> kernelSize, float sigma_min, float sigma_max) : base(nameof(GaussianBlur))
2927
{
30-
return transforms.functional.gaussian_blur(input, kernelSize, new float[] { sigma });
28+
if (kernelSize == null || kernelSize.Count != 2 || kernelSize.Any(x => x <= 0)) {
29+
throw new ArgumentException("Invalid kernel size argument.");
30+
}
31+
if (sigma_min < 0 || sigma_max < 0 || sigma_min > sigma_max) {
32+
throw new ArgumentException("Invalid GaussianBlur arguments: min and max must be positive and min <= max");
33+
}
34+
// Leave 'this.sigma' null.
35+
this.sigma_min = sigma_min;
36+
this.sigma_max = sigma_max;
37+
this.kernelSize = kernelSize.ToArray();
38+
}
39+
40+
public override Tensor forward(Tensor input)
41+
{
42+
var s = sigma.HasValue ? sigma.Value : torch.empty(1).uniform_(sigma_min, sigma_max).item<float>();
43+
return transforms.functional.gaussian_blur(input, kernelSize, stackalloc[]{s, s});
3144
}
3245

3346
protected long[] kernelSize;
34-
protected float sigma;
47+
protected float? sigma;
48+
protected float sigma_min;
49+
protected float sigma_max;
3550
}
3651

3752
public static partial class transforms
@@ -44,7 +59,7 @@ public static partial class transforms
4459
/// <returns></returns>
4560
static public ITransform GaussianBlur(IList<long> kernelSize, float sigma)
4661
{
47-
return new GaussianBlur(kernelSize, sigma, sigma);
62+
return new GaussianBlur(kernelSize, sigma);
4863
}
4964

5065
/// <summary>

test/TorchSharpTest/TestTorchTensorBugs.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1681,5 +1681,26 @@ public void ValidateLoadWithDeflateStream()
16811681
}
16821682
#endif
16831683
}
1684+
1685+
[Fact]
1686+
public void Validate1400()
1687+
{
1688+
long kernel = 21;
1689+
float sigma = 11;
1690+
var trans = torchvision.transforms.GaussianBlur(kernel, sigma); //System.ArgumentException:“Invalid GaussianBlur arguments.”
1691+
1692+
var img = torch.rand(1,3,256,256);
1693+
var t = trans.call(img);
1694+
}
1695+
1696+
[Fact]
1697+
public void Validate1402()
1698+
{
1699+
var t = torch.arange(100).reshape(10,10);
1700+
1701+
var d = t.diagonal();
1702+
1703+
Assert.Equal(new long[]{0, 11, 22, 33, 44, 55, 66, 77, 88, 99}, d.data<long>().ToArray());
1704+
}
16841705
}
16851706
}

0 commit comments

Comments
 (0)