diff --git a/pynamodb/models.py b/pynamodb/models.py
index 2425106..1e539de 100644
--- a/pynamodb/models.py
+++ b/pynamodb/models.py
@@ -344,7 +344,6 @@ class Model(AttributeContainer):
         attribute_cls = None
         for attr_name, attr_cls in self._get_attributes().items():
             if attr_name == attribute:
-                value = attr_cls.serialize(value)
                 attribute_cls = attr_cls
                 break
         if not attribute_cls:
@@ -360,8 +359,10 @@ class Model(AttributeContainer):
                 ACTION: action.upper() if action else None,
             }
         }
-        if action is not None and action.upper() != DELETE:
-            kwargs[pythonic(ATTR_UPDATES)][attribute_cls.attr_name][VALUE] = {ATTR_TYPE_MAP[attribute_cls.attr_type]: value}
+        if value is not None:
+            kwargs[pythonic(ATTR_UPDATES)][attribute_cls.attr_name][VALUE] = {
+                ATTR_TYPE_MAP[attribute_cls.attr_type]: attribute_cls.serialize(value)
+            }
         kwargs[pythonic(RETURN_VALUES)] = ALL_NEW
         kwargs.update(conditional_operator=conditional_operator)
         kwargs.update(condition=condition)
@@ -415,7 +416,7 @@ class Model(AttributeContainer):
             attribute_cls = attrs[attr]
             action = params['action'] and params['action'].upper()
             attr_values = {ACTION: action}
-            if action != DELETE:
+            if 'value' in params:
                 attr_values[VALUE] = self._serialize_value(attribute_cls, params['value'])
 
             kwargs[pythonic(ATTR_UPDATES)][attribute_cls.attr_name] = attr_values

update_item delete item from set fails
Here is a simple test case that attempts to remove an value from a UnicodeSet attribute:

``` python
from pynamodb.models import Model
from pynamodb.attributes import NumberAttribute, UnicodeSetAttribute


class UserModel(Model):

    class Meta:
        table_name = 'User'
        region = 'us-west-2'
        read_capacity_units = 1
        write_capacity_units = 1
        host = 'http://localhost:8000'

    id = NumberAttribute(hash_key=True)
    nicknames = UnicodeSetAttribute(null=True)


UserModel.create_table(wait=True)
try:
    original_nicknames = {'name1', 'name2', 'name3'}
    nicknames_to_remove = {'name2'}
    expected_result_nicknames = original_nicknames - nicknames_to_remove
    user = UserModel(id=1, nicknames=original_nicknames)
    user.save()
    user = UserModel.get(1)
    print('original nicknames:', user.nicknames)
    assert original_nicknames == user.nicknames
    print('nicknames to remove:', nicknames_to_remove)
    user.update_item('nicknames', value=nicknames_to_remove, action='delete')
    user = UserModel.get(1)
    print('expected result nicknames:', expected_result_nicknames)
    print('  actual result nicknames:', user.nicknames)
    print()
    assert expected_result_nicknames == user.nicknames
finally:
    UserModel.delete_table()
```

When running this test case, the output is:

```
original nicknames: {'name2', 'name3', 'name1'}
nicknames to remove: {'name2'}
expected result nicknames: {'name3', 'name1'}
  actual result nicknames: None

Traceback (most recent call last):
  File "mytest.py", line 34, in <module>
    assert expected_result_nicknames == user.nicknames
AssertionError
```

I expected 'name2' to be removed from the `{'name1', 'name2', 'name3'}` set, but instead all the values were removed.

This bug exists since 1.4.4 (1.4.3 works fine), and is still present in 1.6.0. The associated pull request has been updated to be be based on the post 1.6.0 devel branch, and it includes a unit test that fails with only the 'pynamodb/tests' commits applied but succeeds with the changes to connection/base.py and models.py (for update_item of connection and model, respectively).

diff --git a/pynamodb/tests/test_model.py b/pynamodb/tests/test_model.py
index 571c1e3..2688fb4 100644
--- a/pynamodb/tests/test_model.py
+++ b/pynamodb/tests/test_model.py
@@ -1080,6 +1080,44 @@ class ModelTestCase(TestCase):
             assert item.views is None
             self.assertEquals(set(['bob']), item.custom_aliases)
 
+        # Reproduces https://github.com/pynamodb/PynamoDB/issues/132
+        with patch(PATCH_METHOD) as req:
+            req.return_value = {
+                ATTRIBUTES: {
+                    "aliases": {
+                        "SS": set(["alias1", "alias3"])
+                    }
+                }
+            }
+            item.update({
+                'custom_aliases': {'value': set(['alias2']), 'action': 'delete'},
+            })
+
+            args = req.call_args[0][1]
+            params = {
+                'TableName': 'SimpleModel',
+                'ReturnValues': 'ALL_NEW',
+                'Key': {
+                    'user_name': {
+                        'S': 'foo'
+                    }
+                },
+                'UpdateExpression': 'DELETE #0 :0',
+                'ExpressionAttributeNames': {
+                    '#0': 'aliases'
+                },
+                'ExpressionAttributeValues': {
+                    ':0': {
+                        'SS': set(['alias2'])
+                    }
+                },
+                'ReturnConsumedCapacity': 'TOTAL'
+            }
+            deep_eq(args, params, _assert=True)
+
+            assert item.views is None
+            self.assertEquals(set(['alias1', 'alias3']), item.custom_aliases)
+
     def test_update_item(self):
         """
         Model.update_item
@@ -1577,6 +1615,38 @@ class ModelTestCase(TestCase):
             }
             deep_eq(args, params, _assert=True)
 
+        # Reproduces https://github.com/pynamodb/PynamoDB/issues/132
+        with patch(PATCH_METHOD) as req:
+            req.return_value = {
+                ATTRIBUTES: {
+                    "aliases": {
+                        "SS": set(["alias1", "alias3"])
+                    }
+                }
+            }
+            item.update_item('custom_aliases', set(['alias2']), action='delete')
+            args = req.call_args[0][1]
+            params = {
+                'TableName': 'SimpleModel',
+                'ReturnValues': 'ALL_NEW',
+                'Key': {
+                    'user_name': {
+                        'S': 'foo'
+                    }
+                },
+                'UpdateExpression': 'DELETE #0 :0',
+                'ExpressionAttributeNames': {
+                    '#0': 'aliases'
+                },
+                'ExpressionAttributeValues': {
+                    ':0': {
+                        'SS': set(['alias2'])
+                    }
+                },
+                'ReturnConsumedCapacity': 'TOTAL'
+            }
+            deep_eq(args, params, _assert=True)
+            self.assertEqual(set(["alias1", "alias3"]), item.custom_aliases)
 
     def test_save(self):
         """

pip install -e .[dev]
parse_log_pytest
requirements.txt
pytest
3.6
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
attrs==22.2.0
botocore==1.2.0
certifi==2021.5.30
docutils==0.18.1
importlib-metadata==4.8.3
iniconfig==1.1.1
jmespath==0.7.1
packaging==21.3
pluggy==1.0.0
py==1.11.0
-e git+https://github.com/pynamodb/PynamoDB.git@c4d89e95bc747173651d5a529992a2ca8f03bddb#egg=pynamodb
pyparsing==3.1.4
pytest==7.0.1
python-dateutil==2.9.0.post0
six==1.9.0
tomli==1.2.3
typing_extensions==4.1.1
zipp==3.6.0

name: PynamoDB
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2021.5.30=py36h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.3=he6710b0_2
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=21.2.2=py36h06a4308_0
  - python=3.6.13=h12debd9_1
  - readline=8.2=h5eee18b_0
  - setuptools=58.0.4=py36h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.37.1=pyhd3eb1b0_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - attrs==22.2.0
      - botocore==1.2.0
      - docutils==0.18.1
      - importlib-metadata==4.8.3
      - iniconfig==1.1.1
      - jmespath==0.7.1
      - packaging==21.3
      - pluggy==1.0.0
      - py==1.11.0
      - pyparsing==3.1.4
      - pytest==7.0.1
      - python-dateutil==2.9.0.post0
      - six==1.9.0
      - tomli==1.2.3
      - typing-extensions==4.1.1
      - zipp==3.6.0
prefix: /opt/conda/envs/PynamoDB

pynamodb/tests/test_model.py::ModelTestCase::test_update pynamodb/tests/test_model.py::ModelTestCase::test_update_item
pynamodb/tests/test_model.py::ModelTestCase::test_batch_get pynamodb/tests/test_model.py::ModelTestCase::test_batch_write pynamodb/tests/test_model.py::ModelTestCase::test_batch_write_with_unprocessed pynamodb/tests/test_model.py::ModelTestCase::test_car_model_retrieve_from_db pynamodb/tests/test_model.py::ModelTestCase::test_car_model_with_null_retrieve_from_db pynamodb/tests/test_model.py::ModelTestCase::test_complex_key pynamodb/tests/test_model.py::ModelTestCase::test_complex_model_is_complex pynamodb/tests/test_model.py::ModelTestCase::test_complex_model_retrieve_from_db pynamodb/tests/test_model.py::ModelTestCase::test_conditional_operator_map_attribute pynamodb/tests/test_model.py::ModelTestCase::test_count pynamodb/tests/test_model.py::ModelTestCase::test_count_no_hash_key pynamodb/tests/test_model.py::ModelTestCase::test_create_model pynamodb/tests/test_model.py::ModelTestCase::test_delete pynamodb/tests/test_model.py::ModelTestCase::test_delete_doesnt_do_validation_on_null_attributes pynamodb/tests/test_model.py::ModelTestCase::test_deserializing_map_four_layers_deep_works pynamodb/tests/test_model.py::ModelTestCase::test_deserializing_new_style_bool_false_works pynamodb/tests/test_model.py::ModelTestCase::test_deserializing_new_style_bool_true_works pynamodb/tests/test_model.py::ModelTestCase::test_deserializing_old_style_bool_false_works pynamodb/tests/test_model.py::ModelTestCase::test_deserializing_old_style_bool_true_works pynamodb/tests/test_model.py::ModelTestCase::test_dumps pynamodb/tests/test_model.py::ModelTestCase::test_explicit_raw_map_serialize_pass pynamodb/tests/test_model.py::ModelTestCase::test_filter_count pynamodb/tests/test_model.py::ModelTestCase::test_get pynamodb/tests/test_model.py::ModelTestCase::test_global_index pynamodb/tests/test_model.py::ModelTestCase::test_index_count pynamodb/tests/test_model.py::ModelTestCase::test_index_multipage_count pynamodb/tests/test_model.py::ModelTestCase::test_index_queries pynamodb/tests/test_model.py::ModelTestCase::test_invalid_car_model_with_null_retrieve_from_db pynamodb/tests/test_model.py::ModelTestCase::test_invalid_map_model_raises pynamodb/tests/test_model.py::ModelTestCase::test_list_of_map_works_like_list_of_map pynamodb/tests/test_model.py::ModelTestCase::test_list_works_like_list pynamodb/tests/test_model.py::ModelTestCase::test_loads pynamodb/tests/test_model.py::ModelTestCase::test_local_index pynamodb/tests/test_model.py::ModelTestCase::test_model_attrs pynamodb/tests/test_model.py::ModelTestCase::test_model_subclass_attributes_inherited_on_create pynamodb/tests/test_model.py::ModelTestCase::test_model_with_invalid_data_does_not_validate pynamodb/tests/test_model.py::ModelTestCase::test_model_with_list pynamodb/tests/test_model.py::ModelTestCase::test_model_with_list_of_map pynamodb/tests/test_model.py::ModelTestCase::test_model_with_list_of_map_retrieve_from_db pynamodb/tests/test_model.py::ModelTestCase::test_model_with_list_retrieve_from_db pynamodb/tests/test_model.py::ModelTestCase::test_model_with_maps pynamodb/tests/test_model.py::ModelTestCase::test_model_with_maps_retrieve_from_db pynamodb/tests/test_model.py::ModelTestCase::test_model_with_maps_with_nulls_retrieve_from_db pynamodb/tests/test_model.py::ModelTestCase::test_model_with_maps_with_pythonic_attributes pynamodb/tests/test_model.py::ModelTestCase::test_model_with_nulls_validates pynamodb/tests/test_model.py::ModelTestCase::test_model_works_like_model pynamodb/tests/test_model.py::ModelTestCase::test_multiple_indices_share_non_key_attribute pynamodb/tests/test_model.py::ModelTestCase::test_new_style_boolean_serializes_as_bool pynamodb/tests/test_model.py::ModelTestCase::test_old_style_boolean_serializes_as_bool pynamodb/tests/test_model.py::ModelTestCase::test_old_style_model_exception pynamodb/tests/test_model.py::ModelTestCase::test_overidden_defaults pynamodb/tests/test_model.py::ModelTestCase::test_overidden_session pynamodb/tests/test_model.py::ModelTestCase::test_overridden_attr_name pynamodb/tests/test_model.py::ModelTestCase::test_projections pynamodb/tests/test_model.py::ModelTestCase::test_query pynamodb/tests/test_model.py::ModelTestCase::test_query_limit_greater_than_available_items_and_page_size pynamodb/tests/test_model.py::ModelTestCase::test_query_limit_greater_than_available_items_multiple_page pynamodb/tests/test_model.py::ModelTestCase::test_query_limit_greater_than_available_items_single_page pynamodb/tests/test_model.py::ModelTestCase::test_query_limit_identical_to_available_items_single_page pynamodb/tests/test_model.py::ModelTestCase::test_query_limit_less_than_available_and_page_size pynamodb/tests/test_model.py::ModelTestCase::test_query_limit_less_than_available_items_multiple_page pynamodb/tests/test_model.py::ModelTestCase::test_rate_limited_scan pynamodb/tests/test_model.py::ModelTestCase::test_raw_map_as_sub_map pynamodb/tests/test_model.py::ModelTestCase::test_raw_map_as_sub_map_deserialize pynamodb/tests/test_model.py::ModelTestCase::test_raw_map_as_sub_map_from_raw_data_works pynamodb/tests/test_model.py::ModelTestCase::test_raw_map_as_sub_map_serialize_pass pynamodb/tests/test_model.py::ModelTestCase::test_raw_map_deserializes pynamodb/tests/test_model.py::ModelTestCase::test_raw_map_from_raw_data_works pynamodb/tests/test_model.py::ModelTestCase::test_raw_map_serialize_fun_one pynamodb/tests/test_model.py::ModelTestCase::test_refresh pynamodb/tests/test_model.py::ModelTestCase::test_result_set_init pynamodb/tests/test_model.py::ModelTestCase::test_result_set_iter pynamodb/tests/test_model.py::ModelTestCase::test_save pynamodb/tests/test_model.py::ModelTestCase::test_scan pynamodb/tests/test_model.py::ModelTestCase::test_scan_limit pynamodb/tests/test_model.py::ModelTestCase::test_scan_limit_with_page_size pynamodb/tests/test_model.py::ModelTestCase::test_throttle pynamodb/tests/test_model.py::ModelInitTestCase::test_raw_map_attribute_with_dict_init pynamodb/tests/test_model.py::ModelInitTestCase::test_raw_map_attribute_with_initialized_instance_init pynamodb/tests/test_model.py::ModelInitTestCase::test_subclassed_map_attribute_with_dict_init pynamodb/tests/test_model.py::ModelInitTestCase::test_subclassed_map_attribute_with_initialized_instance_init pynamodb/tests/test_model.py::ModelInitTestCase::test_subclassed_map_attribute_with_map_attribute_member_with_initialized_instance_init pynamodb/tests/test_model.py::ModelInitTestCase::test_subclassed_map_attribute_with_map_attributes_member_with_dict_init
pynamodb/models.py
pynamodb/models.py