Table of Contents#
- What is
torch.cosh()? - Mathematical Background
- Syntax and Parameters
- Example Usage
- Common Practices
- Best Practices
- Potential Pitfalls
- Comparison with NumPy’s
cosh - Conclusion
- References
What is torch.cosh()?#
torch.cosh() is a PyTorch function that computes the hyperbolic cosine of each element in a given input tensor. It operates element-wise, meaning it applies the hyperbolic cosine function to every element individually, returning a new tensor with the same shape as the input.
Formally, for an input tensor x, torch.cosh(x) returns a tensor y where each element y_i = cosh(x_i).
Mathematical Background#
The hyperbolic cosine function is defined as:
[ \cosh(x) = \frac{e^x + e^{-x}}{2} ]
Key Properties:#
- Even Function: (\cosh(-x) = \cosh(x)) (symmetric around the y-axis).
- Range: (\cosh(x) \geq 1) for all real (x) (minimum value of 1 at (x=0)).
- Asymptotic Behavior: For large positive (x), (\cosh(x) \approx \frac{e^x}{2}); for large negative (x), (\cosh(x) \approx \frac{e^{-x}}{2}) (due to the even property).
- Relationship to Trigonometric Cosine: While trigonometric cosine uses circular geometry ((\cos(x) = \frac{e^{ix} + e^{-ix}}{2})), hyperbolic cosine uses hyperbolic geometry.
Syntax and Parameters#
Function Signature:#
torch.cosh(input, *, out=None) → TensorParameters:#
input(Tensor): The input tensor containing elements for which to compute the hyperbolic cosine. Must be a tensor of floating-point dtype (e.g.,float32,float64).out(Tensor, optional): A tensor to store the output. If provided, it must have the same shape asinput.
Returns:#
A new tensor of the same shape as input, with each element replaced by its hyperbolic cosine.
Example Usage#
Let’s explore practical examples to understand how torch.cosh() works.
Basic Examples#
Example 1: 1D Tensor#
Compute cosh for a simple 1D tensor:
import torch
# Create a 1D tensor
x = torch.tensor([-2.0, -1.0, 0.0, 1.0, 2.0])
y = torch.cosh(x)
print("Input tensor:", x)
print("cosh(x):", y)Output:
Input tensor: tensor([-2., -1., 0., 1., 2.])
cosh(x): tensor([3.7622, 1.5431, 1.0000, 1.5431, 3.7622])
Note the symmetry due to the even property of cosh.
Example 2: 2D Tensor#
Compute cosh for a 2D tensor (matrix):
x = torch.tensor([[0.5, 1.0], [1.5, 2.0]])
y = torch.cosh(x)
print("Input tensor:\n", x)
print("cosh(x):\n", y)Output:
Input tensor:
tensor([[0.5000, 1.0000],
[1.5000, 2.0000]])
cosh(x):
tensor([[1.1276, 1.5431],
[2.3524, 3.7622]])
Handling Different Tensor Types#
torch.cosh() works with various floating-point dtypes. Here’s how to use it with float32 and float64:
# float32 (default for PyTorch tensors)
x_float32 = torch.tensor([1.0, 2.0], dtype=torch.float32)
print("float32 cosh:", torch.cosh(x_float32)) # tensor([1.5431, 3.7622])
# float64 (double precision)
x_float64 = torch.tensor([1.0, 2.0], dtype=torch.float64)
print("float64 cosh:", torch.cosh(x_float64)) # tensor([1.54308063, 3.76219569], dtype=torch.float64)Note: Integer tensors will be implicitly cast to float, but it’s best practice to use float dtypes explicitly.
In-Place Operations#
Use the out parameter to store results in an existing tensor (in-place operation):
x = torch.tensor([0.0, 1.0])
out_tensor = torch.empty_like(x) # Preallocate output tensor
torch.cosh(x, out=out_tensor)
print("out_tensor:", out_tensor) # tensor([1.0000, 1.5431])Autograd and Differentiation#
PyTorch’s cosh supports automatic differentiation (autograd), making it suitable for training neural networks. Let’s compute the gradient of cosh(x) at (x=1):
x = torch.tensor([1.0], requires_grad=True)
y = torch.cosh(x)
# Compute gradients
y.backward()
print("cosh(1) =", y.item()) # 1.5430806350708008
print("Gradient dy/dx at x=1:", x.grad) # tensor([1.1752]) (since d/dx cosh(x) = sinh(x), and sinh(1) ≈ 1.1752)Common Practices#
-
Element-Wise Operation:
torch.cosh()operates element-wise, so it works seamlessly with tensors of any shape (scalars, 1D, 2D, or higher-dimensional).# Scalar input (0D tensor) x = torch.tensor(0.0) print(torch.cosh(x)) # tensor(1.0) -
GPU Acceleration: Like most PyTorch operations,
torch.cosh()can run on GPUs for faster computation. Simply move the tensor to the GPU with.to('cuda'):if torch.cuda.is_available(): x_gpu = x.to('cuda') y_gpu = torch.cosh(x_gpu) print("GPU result:", y_gpu) # Same value as CPU, but computed on GPU -
Handling Edge Cases:
torch.cosh()gracefully handles edge cases likeNaNandInf:print(torch.cosh(torch.tensor(float('inf')))) # tensor(inf) print(torch.cosh(torch.tensor(float('nan')))) # tensor(nan)
Best Practices#
-
Use Appropriate Dtypes: Prefer
float32for most deep learning tasks (balances precision and speed). Usefloat64only when higher precision is critical (e.g., scientific computing). -
Avoid Unnecessary In-Place Operations: While
outcan save memory, in-place operations may interfere with autograd’s gradient tracking. Use them only when memory is constrained. -
Clamp Large Inputs: Since
cosh(x)grows exponentially for large (|x|), very large inputs can cause numerical overflow (e.g.,cosh(1000)returnsinf). Clamp inputs to a reasonable range if needed:x = torch.tensor([1000.0]) x_clamped = torch.clamp(x, min=-100, max=100) # Avoid overflow print(torch.cosh(x_clamped)) # Still large but finite -
Leverage Vectorization: Avoid looping over tensor elements;
torch.cosh()is optimized for vectorized operations, making it much faster than element-wise loops.
Potential Pitfalls#
-
Overflow with Large Inputs: As mentioned,
cosh(x)grows exponentially. For (x > 709),cosh(x)exceeds the maximum value offloat64(resulting ininf). Use clamping or consider alternative functions (e.g.,tanhfor bounded outputs) if large inputs are expected. -
Type Errors with Integer Tensors: While PyTorch may implicitly cast integer tensors to float, explicitly using float dtypes avoids unexpected behavior:
x_int = torch.tensor([1, 2], dtype=torch.int32) # torch.cosh(x_int) # Throws RuntimeError: cosh_vml_cpu not implemented for 'Int' x_float = x_int.to(torch.float32) print(torch.cosh(x_float)) # Works: tensor([1.5431, 3.7622]) -
Ignoring Gradient Computation: For training, ensure
requires_grad=Trueis set on input tensors if gradients are needed (as shown in the autograd example).
Comparison with NumPy’s cosh#
PyTorch’s torch.cosh() is similar to NumPy’s numpy.cosh(), but with key differences:
- GPU Support: PyTorch tensors can run on GPUs, while NumPy is CPU-only.
- Autograd: PyTorch integrates with autograd for gradient computation, critical for training models.
- Tensor Compatibility: PyTorch tensors are designed for deep learning workflows (e.g., batch processing, distributed training).
Example comparison:
import numpy as np
# NumPy
x_np = np.array([-1.0, 0.0, 1.0])
y_np = np.cosh(x_np) # array([1.54308063, 1.0, 1.54308063])
# PyTorch
x_pt = torch.tensor(x_np)
y_pt = torch.cosh(x_pt) # tensor([1.5431, 1.0000, 1.5431])Conclusion#
The torch.cosh() method is a versatile tool in PyTorch for computing hyperbolic cosine values element-wise on tensors. Its integration with autograd and GPU acceleration makes it indispensable for deep learning and scientific computing tasks. By understanding its syntax, mathematical properties, and best practices, you can effectively leverage torch.cosh() in applications like activation functions, signal processing, and differential equation solving.