input: Write a python function to perform Fuzzy C-Means clustering and return both cluster centers and membership values.
  assert np.array_equal(fuzzy_cmeans(np.array([[1.3, 2.3, 1.1], [2.2, 3.2, 1.7], [3.1, 4.1, 2.9], [4.2, 5.1, 3.7], [5.3, 6.2, 4.2]]), 3)[0].shape, (3, 3))
  assert np.array_equal(fuzzy_cmeans(np.array([[1.3, 2.3, 1.1], [2.2, 3.2, 1.7], [3.1, 4.1, 2.9], [4.2, 5.1, 3.7], [5.3, 6.2, 4.2]]), 3)[1].shape, (5, 3))
output: import numpy as np
  
  def fuzzy_cmeans(data, num_clusters, m=2, max_iter=100, error=1e-5):
      # Initialize membership matrix U with random values
      num_samples = data.shape[0]
      U = np.random.dirichlet(np.ones(num_clusters), size=num_samples)
      
      for iteration in range(max_iter):
          # Calculate cluster centers
          U_m = U ** m
          centers = U_m.T @ data / np.sum(U_m.T, axis=1, keepdims=True)
          
          # Update membership matrix
          dist = np.linalg.norm(data[:, np.newaxis] - centers, axis=2)
          new_U = 1 / dist ** (2 / (m - 1))
          new_U /= np.sum(new_U, axis=1, keepdims=True)
          
          # Check convergence
          if np.linalg.norm(new_U - U) < error:
              break
          
          U = new_U
      
      return centers, U